我在一个数据库中有一个表,它引用另一个数据库中表的ID。我已设置而不是插入/更新触发器,以防止插入另一个表中不存在的ID。我希望这些触发器在发现不存在的ID时中止事务,否则继续执行事务。
以下是我的尝试:
CREATE TRIGGER [dbo].[tr_check_student_insert]
ON [dbo].[student]
INSTEAD OF INSERT
AS
BEGIN
SET XACT_ABORT ON
IF (EXISTS ... )
BEGIN
RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
END
IF (EXISTS ... )
BEGIN
RAISERROR (N'[class_id] does not exist in [class]',11,1)
END
INSERT INTO [dbo].[student] ...
END
我发现RAISERROR不会中止事务,即使SET XACT_ABORT为ON,并且在引发错误后仍然会发生插入(或更新)。
我知道我可以在IF / ELSE IF语句中包装每个条件,并在ELSE上调用insert,但我只是想知道是否有办法立即退出并回滚整个事务。
答案 0 :(得分:1)
您需要在BEGIN TRANSACTION
ROLLBACK
TRY
和CATCH
尝试这样的事情:
CREATE TRIGGER [dbo].[tr_check_student_insert]
ON [dbo].[student]
INSTEAD OF INSERT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
IF (EXISTS ... )
BEGIN
RAISERROR (N'[teacher_id] does not exist in [teacher]',11,1)
END
IF (EXISTS ... )
BEGIN
RAISERROR (N'[class_id] does not exist in [class]',11,1)
END
INSERT INTO [dbo].[student] ...
;
COMMIT
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
RETURN;
END CATCH
END