我有一个要求要根据某些条件防止在插入后使用插入表。当我直接调用insert语句时,它执行完美,没有任何问题。而在将过程用于具有事务范围的插入语句时,却出现此错误
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
请让我知道是否缺少任何东西
答案 0 :(得分:2)
删除触发器内的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
答案 1 :(得分:1)
从触发器中删除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
答案 2 :(得分:0)
据我了解
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