Триггер для блокировки вставки в SQL Server - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть требование запретить вставку в таблицу после вставки, основываясь на определенных условиях.Когда я вызываю оператор вставки напрямую, он выполняется без проблем.Принимая во внимание, что, когда я использую процедуру для оператора вставки с областью транзакции, я получаю эту ошибку

Запрос ROLLBACK TRANSACTION не имеет соответствующей BEGIN TRANSACTION.

Мой код:

create table test
(
    id int ,
    name varchar(10)
)

create table test1
(
    id int ,
    name varchar(10)
)

ALTER PROCEDURE test_insert 
    @id INT, @name NVARCHAR(10)
AS
BEGIN
    BEGIN TRY
        BEGIN TRANSACTION
            INSERT INTO test1 (id, name) 
            VALUES (@id, @name)

            INSERT INTO test (id, name) 
            VALUES (@id, @name)
       COMMIT
    END TRY
    BEGIN CATCH
        ROLLBACK;

        DECLARE @errormsg NVARCHAR(MAX)

        SELECT @errormsg = ERROR_MESSAGE();
        THROW 500001, @errormsg, 1;  
    END CATCH
end

ALTER TRIGGER TRG_test
ON dbo.test
AFTER INSERT AS
BEGIN
    DECLARE @idNum INT

    SELECT @idNum = id FROM inserted

    IF @idNum = 1
    BEGIN
        RAISERROR('error', 1,1);
        ROLLBACK TRANSACTION
        RETURN  
    END
END

Пожалуйста, дайте мне знать, если мне что-то не хватает

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Насколько я понимаю,

alter TRIGGER TRG_test
ON dbo.test
instead of insert as --- Trigger type is changed. Trigged before insert
BEGIN
    declare @idNum int
    select @idNum = id from inserted

    if @idNum <> 1 ------ Condition is changed
        begin

        /* Do what you want.*/

        RETURN  
    end
END

обновление 1:

create table test(
    id int ,
    name varchar(10)
)

create table test11(
    id int ,
    name varchar(10)
)



alter proc test_insert @id int, @name nvarchar(10)
as
begin
    BEGIN TRY
        BEGIN TRANSACTION
        insert into test11(id,name) values(@id,@name)
        insert into test (id,name) values(@id,@name)
       COMMIT
    END TRY
    BEGIN CATCH
        ROLLBACK;
        declare @errormsg nvarchar(max)
        select @errormsg=ERROR_MESSAGE();
        THROW 500001, @errormsg, 1;  
    END CATCH
end

alter TRIGGER TRG_test
ON dbo.test
instead of insert as --- Trigger type is changed. Trigged before insert
BEGIN
    declare @idNum int, @name int
    select @idNum = id, @name=name from inserted

    if @idNum <> 1 ------ Condition is changed
        begin

        insert into test (id,name) values(@idNum,@name)
    end
    else begin

     print 'You insert invalid value 1'

    end
END

test_insert 1, 2 -- error will be arised.

select * from test
select * from test11

test_insert 2, 2 -- insertion is occurs.

select * from test
select * from test11
0 голосов
/ 18 декабря 2018

Удалите ROLLBACK из триггера и поднимите и выполните ошибку со степенью серьезности 11 или выше, чтобы ввести блок хранимой процедуры CATCH.Приведенный ниже код также использует упрощенную версию THROW, чтобы вызвать ошибку триггера, вместо выдачи новой, и использует EXISTS для обработки многострочных вставок.

alter proc test_insert @id int, @name nvarchar(10)
as
begin
    BEGIN TRY
        BEGIN TRANSACTION
        insert into test1 (id,name) values(@id,@name)
        insert into test (id,name) values(@id,@name)
       COMMIT
    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0 ROLLBACK;
        THROW;
    END CATCH
end
GO
alter TRIGGER TRG_test
ON dbo.test
AFTER INSERT AS
BEGIN
    if EXISTS(select 1 from inserted WHERE id = 1)
        begin
        RAISERROR('error', 16,1);
        RETURN  
    end
END
GO
0 голосов
/ 18 декабря 2018

Удалите ROLLBACK TRANSACTION внутри триггера, помните, что операторы DML в триггере будут использовать контекст транзакции оператора, который запустил триггер, в этом случае он будет покрываться:

 Your SP ==>

  BEGIN TRANSACTION
      --Fired the trigger and is involved by the same Transaction from the SP
        insert into test1 (id,name) values(@id,@name)  
        insert into test (id,name) values(@id,@name)
       COMMIT  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...