I have a requirement to prevent insert into table using after insert based on certain condition. When I am calling insert statement directly, it is executing perfectly without any problem. Whereas when am using procedure for insert statement with transaction scope, I am getting this error
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
My code:
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
Please let me know if am missing anything
Remove the ROLLBACK TRANSACTION inside the Trigger, remember that DML statements within the trigger will use the transaction context of the statement that fired the trigger, in this case, it would be covered by:
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
Remove the ROLLBACK
from the trigger and raise and error with severity 11 or higher so that the stored procedure CATCH
block is entered. The code below also uses the simplified version of THROW
to reraise the trigger error instead of throwing a new one and uses EXISTS
to handle multi-row inserts.
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
From my understanding,
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
update 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.