Выполните хранимую процедуру для обновления каждой строки перед вставкой - PullRequest
0 голосов
/ 11 октября 2019

Я пишу триггер INSTEAD OF INSERT для перехвата вставленных данных и заполнения столбца 2.

Мне нужно выполнить хранимую процедуру, которая возвращает значение для вставки в столбец 2.
Хранимая процедуравозвращает новое значение каждый раз, когда оно выполняется (crypto prng).

Поэтому, если кто-то вставляет 10 строк, мой триггер должен выполнить хранимую процедуру 10 раз и заполнить каждую строку одним из возвращенных значений.

Я слышал, что для чего-то подобного редко нужно использовать курсоры.
Но я не уверен, что стандартный цикл также является лучшим подходом.

Есть ли более обтекаемыйспособ достижения этого в операторе SELECT, UPDATE или INSERT?

CREATE TRIGGER dbo.table1_instead_of_insert
ON dbo.table1
INSTEAD OF INSERT
AS BEGIN
    DECLARE @i BIGINT ;
    EXECUTE dbo.proc1 @1 ;
    --proc1 sets the value of @i to a different value each time proc1 is executed
    --(crypto prng)

    --Update the value of column2 in INSERTED, setting it to the value of @i

    --Repeat this process for each row in INSERTED,
      --with proc1 returning a different value for each row

    INSERT INTO dbo.table1 ( column1 , column2 )
        SELECT column1 , column2 FROM INSERTED ;
END
GO

1 Ответ

1 голос
/ 11 октября 2019

Попробуйте это:

CREATE TRIGGER dbo.table1_instead_of_insert
ON dbo.table1
INSTEAD OF INSERT
AS BEGIN

    CREATE TABLE #DataSource
    (
        [RowID] INT IDENTITY(1,1) 
       ,[Column1] VARCHAR(12) -- use your type
       ,[Column2] VARCHAR(12) -- use your type
    );

    INSERT INTO #DataSource ([Column1], [Column2])
    SELECT [Column1], [Column2]
    FROM inserted;

    DECLARE @RowID TINYINT = 1;
    DECLARE @i BIGINT ;

    WHILE(EXISTS(SELECT 1 FROM #DataSource WHERE [RowID] = @RowID))
    BEGIN;

         EXECUTE dbo.proc1 @i ;

         UPDATE #DataSource
         SET [Column2] = @i
         WHERE [RowID] = @RowID;

        SET @RowID = @RowID + 1;
    END;    

    INSERT INTO dbo.table1 ( column1 , column2 )
        SELECT column1 , column2 FROM #DataSource ;
END
GO

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

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

Вы должны проверить эту ссылку тоже.

...