если я хочу сделать несколько операций над каждой строкой набора результатов - PullRequest
2 голосов
/ 28 апреля 2011

Если я хочу сделать несколько операций над каждой строкой набора результатов, я должен использовать цикл или курсор. Есть ли другой эффективный или удобный способ сделать это? Я пишу длинную хранимую процедуру, я использовал курсор только для чтения для внешнего цикла. Мне также нужен некоторый цикл внутри цикла. (Я новый программист, и мой английский не очень хороший, я надеюсь, что кто-нибудь мне поможет.)

1 Ответ

1 голос
/ 28 апреля 2011

В вашем вопросе все еще недостаточно информации, чтобы дать хороший ответ. Я поделюсь некоторым кодом, который может быть «адекватным», чтобы помочь вам увидеть один из способов переадресации вопроса, чтобы избежать курсоров / циклов. Скажем, у нас есть таблица, которую мы используем в качестве очереди (называемой очередью). В этом простом примере все, что мы храним, это значение (Action), которое мы хотим вставить позже в другую таблицу (называемую Target):

create table Queue (
    QueueID int IDENTITY(1,1) not null,
    Action varchar(10) not null,
    Processed bit not null,
    TargetID int null,
    constraint PK_Queue PRIMARY KEY (QueueID),
    constraint CK_Queue_Processed CHECK ( Processed = 0 or TargetID is not null)
)
go
create table Target (
    TargetID int IDENTITY(1,1) not null,
    Action varchar(10) not null,
    constraint PK_Target PRIMARY KEY (TargetID)
)

Обратите внимание, что после обработки элемента из таблицы очереди мы хотим пометить его как обработанный (Processed = 1) и узнать, какую строку мы в конечном итоге вставили в целевую таблицу (TargetID).

Итак, давайте создадим несколько строк для обработки:

insert into Queue(Action,Processed)
select 'abc',0 union all
select 'def',0 union all
select 'ghi',0

А теперь мы обработаем эту очередь, сначала вставив строки в целевую таблицу, а затем соответствующим образом обновим таблицу очередей:

declare @Inter table (QueueID int not null,TargetID int not null)

;merge into Target using (select QueueID,Action from Queue where Processed=0) Queue
on 1=0
when not matched then insert (Action) values (Action)
output Queue.QueueID,inserted.TargetID into @Inter (QueueID,TargetID);

update q
set
    Processed = 1,
    TargetID = i.TargetID
from
    Queue q
        inner join
    @Inter i
        on
            q.QueueID = i.QueueID

Мы могли бы использовать более простое выражение insert (вместо merge), если бы мы вставляли в целевую таблицу достаточно информации (например, QueueID), чтобы мы могли извлечь все, что нам нужно, в @Inter таблица из inserted псевдо таблицы.

И, наконец, мы проверяем обе таблицы, чтобы убедиться, что они работают так, как мы ожидали:

select * from Queue
select * from Target

На моем компьютере идентификаторы TargetID, назначенные строкам, соответствуют идентификаторам QueueID, но это не гарантируется.

Выше приведен доработка моего ответа на Как можно избежать использования курсора для реализации этого псевдокода - SQL Server , который включал выполнение дополнительной вставки во вторую таблицу перед обновлением исходной таблицы .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...