Обновление с последующей вставкой в ​​хранимую процедуру - PullRequest
3 голосов
/ 25 марта 2019

Я не уверен, что это правильный способ сделать обновление с последующей вставкой в ​​хранимую процедуру.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[io_sp_admin_add_emp]
    @id BIGINT,
    @lastName VARCHAR(20), 
    @firstName VARCHAR(20)
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRY
    BEGIN TRANSACTION [TranAddEmp]
       DECLARE @identity BIGINT = 0 

       INSERT INTO empTable(LastName, FirstName, hash_id)
       VALUES (@lastName, @firstName,
               HashBytes('SHA2_256', CAST(@id AS VARBINARY(50))))

       SELECT @identity = @@identity

       UPDATE empTable
       SET rowId = incId  -- both are columns in empTable
       WHERE hash_id = @identity

       COMMIT TRANSACTION [TranAddEmp]   
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION [TranAddEmp]
    END CATCH                  
END

Ответы [ 2 ]

4 голосов
/ 25 марта 2019

Простое изменение вашего текущего кода может дать вам то, что вы ищете. Вместо того, чтобы возиться с @@Identity, что почти никогда не подходит, вы один раз вычисляете хэш значения @Id, сохраняете его в локальной переменной и используете как для оператора insert, так и для where предложение оператора update - то есть, если столбец HashId уникален.

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

Вот улучшенная версия вашей хранимой процедуры:

CRETAE PROCEDURE [dbo].[io_sp_admin_add_emp]
    @id BIGINT,
    @lastName varchar(20), 
    @firstName varchar(20)      
AS

BEGIN
    SET NOCOUNT ON;

    BEGIN TRY
        BEGIN TRANSACTION [TranAddEmp]

        -- Compute the hash once, store in a local variable
        DECLARE @HashId varbinary(8000) = HashBytes('SHA2_256', cast(@id as varbinary(50)))

        INSERT INTO empTable(
            LastName,
            FirstName,
            hash_id
        )
        VALUES(
            @lastName,
            @firstName,
            @HashId
        )

         UPDATE empTable
         SET rowId = incId  
         WHERE hash_id = @HashId

        COMMIT TRANSACTION [TranAddEmp]   
    END TRY

    BEGIN CATCH
        -- make sure transaction has started and is not commited
        IF @@TRANCOUNT > 0
            ROLLBACK TRANSACTION [TranAddEmp]
    END CATCH
END
2 голосов
/ 25 марта 2019

Есть отличное ключевое слово OUTPUT. Как говорится в MSDN :

Возвращает информацию или выражения на основе каждой затронутой строки оператором INSERT, UPDATE, DELETE или MERGE. Эти результаты могут быть возвращается в приложение обработки для использования в таких вещах, как подтверждающие сообщения, архивирование и другие подобные приложения требования. Результаты также могут быть вставлены в таблицу или таблицу переменная. Кроме того, вы можете захватить результаты ВЫХОДА предложение во вложенном операторе INSERT, UPDATE, DELETE или MERGE и вставьте эти результаты в целевую таблицу или представление.

Вы можете вставить вставленные идентификаторы в таблицу с помощью ключевого слова OUTPUT. Например:

DECLARE @InsertedIDs TABLE (ID varbinary(8000))

INSERT INTO empTable(
    LastName,
    FirstName,
    hash_id
 )
OUTPUT HashBytes('SHA2_256', cast(INSERTED.ID as varbinary(50))) INTO @InsertedIDs(ID)
 VALUES(
 @lastName,
 @firstName,
 HashBytes('SHA2_256', cast(@id as varbinary(50)))
 )

UPDATE empTable
Set rowId = incId  -- both are columns in empTable
WHERE hash_id in (SELECT ID IN @InsertedIDs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...