-1

假设我的数据库中有 3 个表,如下所示:

  • Person( personid, ...) ---这是实体,personid是标识列
  • Phone( phoneid, ...) ---这是实体,phoneid是标识列
  • PersonPhone( personid, phoneid) ---这种关系

在向表中插入数据时,需要先向实体表中插入行并获取生成的id,然后再向关系表中插入一行。

它工作正常。问题是:我有一个带有事务的存储过程,Try Catch语句如下:

BEGIN TRY
declare aCursor cursor local fast_forward for (Select Query...)

open aCursor;
fetch next from aCursor into @variables....

while @@fetch_status = 0
begin

   INSERT INTO Person(...);
   set @personid =@@IDENTITY;

   INSERT INTO Phone(...);
   set @phoneid =@@IDENTITY;

   INSERT INTO PersonPhone(@personid, @phoneid);       
end; 

END TRY
BEGIN CATCH
    close aCursor;
    deallocate selectdistributor;
     SELECT ERROR_NUMBER() AS ErrorNumber,ERROR_MESSAGE() AS ErrorMessage;    
    ROLLBACK TRAN;
    RETURN;
END CATCH  
COMMIT;  
close aCursor;
deallocate aCursor;

使用光标,将为人员、电话插入更多的一条记录。运行 SP 时,它会在关系上首次插入数据时停止。我也可以得到正确的@personid,@phoneid,但在交易完成之前,我收到错误 INSERT INTO PersonPhone(@personid, @phoneid); 作为:

INSERT 语句与 FOREIGN KEY 约束“Person_PersonPhone_FK1”冲突。冲突发生在数据库“MYDB”、表“dbo.Person”、列“PersonID”中。

看起来系统生成的 ID 在事务完成之前无法识别。

如何解决这个问题?

4

1 回答 1

0

您的问题很可能是您使用了 @@identity ,在任何情况下都不应将其用于此目的。如果其中一个表有触发器,则可能返回错误的值(触发器插入的表中的标识)并且该值巧合地不存在于外键链接到的表中。

因此,假设您在第一个表上有一个触发器,该触发器向具有标识的审计表插入。插入记录的 ID 为 1234。但是,触发器插入到不同的表中,因此@@Identity 返回的值是 5678,它不存在于原始表中。当您将 FK 插入第一个表上的表时,您会收到错误消息,因为第一个表中不存在值 5678。

请改用 OUTPUT 子句。您也可以使用 scope_identity(),但输出更灵活(并且允许您执行多个记录插入并接收所有身份以及可能唯一标识记录的其他字段。

我和 Aaron 在一起,除非有人威胁我的生命,否则我不会使用光标。

于 2013-04-22T19:00:16.687 回答