用于INSERT命令的TRY - CATCH块的SQL触发器故障

时间:2013-11-29 17:07:35

标签: sql sql-server triggers

好的,所以我想创建一个触发器,当有人试图插入表“products”并检查有效的外键时触发。就目前而言(这不是最终的设计,但我用它进行测试),我希望触发器检查插入的行是否引用了Manufacturer表中的有效ID,如果没有这样的行存在在制造商表中,插入一个具有正确ID的信息以及其余字段的一些一般信息。我目前的代码如下:

create trigger checkman
on dbo.products
instead of insert
as
declare
@manid char(5),
@manName varchar(50),
@transactionName varchar(20) = 'transaction1'

Begin
select @manid=Man_ID from Inserted

begin try
    /*begin tran @transactionName*/
    Insert into Manufacturers (Man_ID, Man_Name, Man_Description) VALUES     @manid, 'Unknown Name', 'This is an unknown manufacturer');
    insert into dbo.products select * from inserted;
end try
begin catch
    /*rollback tran @transactionName;*/
    insert into dbo.products select * from inserted;
end catch



End

问题在于,每当我使用已存在的制造商ID运行插件时,我都会收到此错误:

(0 row(s) affected)
Msg 3930, Level 16, State 1, Procedure checkman, Line 20
The current transaction cannot be committed and cannot support operations that write to        the log file. Roll back the transaction.
The statement has been terminated.

当我在catch块中放入“Insert into Manufacturers”行时,我得到了同样的错误,只是这次我尝试插入一个尚不存在的ID时出现。

2 个答案:

答案 0 :(得分:1)

不要在try / catch块中处理这个,没有必要。此外,您需要考虑inserted可以包含多行的事实。您可以使用NOT EXISTS查询执行此操作:

CREATE TRIGGER CheckMan
ON dbo.products
INSTEAD OF INSERT
AS
    INSERT Manufacturers (Man_ID, Man_Name, Man_Description)
    SELECT  DISTINCT Man_ID, 'Unknown Name', 'This is an unknown manufacturer'
    FROM    inserted i
    WHERE   NOT EXISTS
            (   SELECT  1
                FROM    Manufacturers m
                WHERE   m.Man_ID = i.Man_ID
            );

    INSERT  dbo.Products
    SELECT  *
    FROM    inserted;

HOWEVER ,我不提倡这种方法,我认为仅依靠外键本身提供的参照完整性会更好,如果Man_ID不存在则让插入失败,如有必要,确保所有Man_ID存在之前甚至尝试插入。

答案 1 :(得分:0)

我将触发器更改为以下内容。在这样做时,我做了一些隐含的假设。假设这里的Products是一个3列表(col1& col2是除Man_ID之外的其他列)。

希望这有帮助

alter
 trigger checkman
on dbo.products
instead of insert
as
declare
@manid char(5),
@col1 varchar(50),
@transactionName varchar(20) = 'transaction1',
@col2 Varchar(500) 
Begin
select @manid=Man_ID, @col1 = col1, @col2 = col2 from Inserted

IF (NOT EXISTS (SELECT Man_ID
      FROM Manufacturers Where Man_ID = @manid
      ))
   INSERT INTO ManuFacturers (Man_ID, Man_name, Man_Description) Values    (@manid, 'Unknown Name', 'This is an unknown manufacturer')

   INSERT INTO Products (Man_ID, col1, col2) values (@manid, @col1, @col2)

--begin try
--    /*begin tran @transactionName*/
--    Insert into Manufacturers (Man_ID, Man_Name, Man_Description) VALUES     (@manid, 'Unknown Name', 'This is an unknown manufacturer')
--    insert into dbo.products select * from inserted;
--end try
--begin catch
--    /*rollback tran @transactionName;*/
--    insert into dbo.products select * from inserted;
--end catch



End