Sql server 使用@@IDENTITY的正确方法是什么

Sql server 使用@@IDENTITY的正确方法是什么,sql-server,Sql Server,关于@@IDENTITY的问题,我有4个不同的表: 客户[Id] 人员[Id,fname,lname] 账户[Cd、所有者、余额] 交易记录[Id、帐户、类型] 客户Id具有标识增量1的功能 我的目标是为数据库创建一个新人,以便 Customer.Id = Person.Id = Account.owner = Transaction.ID 我尝试了以下操作,但出现了此错误: 无法在列所有者中插入空值 我如何纠正错误,使其正常工作 BEGIN TRAN BEGIN TRY

关于
@@IDENTITY
的问题,我有4个不同的表:

  • 客户[Id]
  • 人员[Id,fname,lname]
  • 账户[Cd、所有者、余额]
  • 交易记录[Id、帐户、类型]
客户Id具有标识增量1的功能

我的目标是为数据库创建一个新人,以便

Customer.Id = Person.Id = Account.owner = Transaction.ID 
我尝试了以下操作,但出现了此错误:

无法在列所有者中插入空值

我如何纠正错误,使其正常工作

BEGIN TRAN 
    BEGIN TRY
 
      INSERT INTO bank.customer DEFAULT VALUES
      
      INSERT INTO bank.person (id, fname, lname)
      VALUES (@@IDENTITY, 'Mike', 'Phelps')

      INSERT INTO bank.account (cd, owner, balance)
      VALUES (2, @@IDENTITY, 0)

      INSERT INTO bank.transaction (id, account, type)
      VALUES (@@IDENTITY, (SELECT cd FROM pankki.tili,'P')

END TRY
BEGIN CATCH
    ROLLBACK
    SELECT
        ERROR_NUMBER() AS ErrorNumber,
        ERROR_STATE() AS ErrorState,
        ERROR_SEVERITY() AS ErrorSeverity,
        ERROR_PROCEDURE() AS ErrorProcedure,
        ERROR_LINE() AS ErrorLine,
        ERROR_MESSAGE() AS ErrorMessage;
END CATCH

我想你想要的是:


开始尝试
开始训练;
声明@ID int--小数点?
在bank.customer中插入默认值;
设置@ID=SCOPE_IDENTITY()--假设客户有一个具有标识的列
插入bank.person(id、fname、lname)
值(@ID,'Mike','Phelps');
插入银行账户(cd、所有者、余额)
值(2,@ID,0);
插入银行交易记录(id、帐户、类型)
选择@ID,
光盘
“P”
来自pankki.tili--因此,我假设pankki.tili只有一行
承诺--你错过了这个
结束尝试
开始捕捉
回降;
投掷--不要选择错误详细信息,将其抛出。
端接

首先,您需要了解这两个命令之间的区别:

  • @@identity
    返回当前会话中任何表中最后插入的标识值,而不考虑范围
  • IDENT_CURRENT('table_或_view')
    返回给定表的上一次插入的标识值
  • 因此,对于您的情况,您需要使用第二个

    你的剧本应该是这样的:

    BEGIN TRAN 
        BEGIN TRY
     
          INSERT INTO bank.customer DEFAULT VALUES
          
          SET @customerID = (SELECT IDENT_CURRENT('bank.customer'))
          
          INSERT INTO bank.person (id,fname,lname)
          VALUES( @customerID,'Mike','Phelps')
    
          INSERT INTO bank.account (cd,owner,balance)
          VALUES(2,@customerID,0)
    
          INSERT INTO bank.transaction(id,account,type)
          VALUES(@customerID,(SELECT cd FROM pankki.tili,'P')
    
    END TRY
    
    这样,您可以保证在四个表中插入相同的ID。
    如果您使用的是
    @@identity
    ,则此值会随着每次新插入而更改。

    来自Microsoft文档:

    INSERT、SELECT INTO或bulk copy语句完成后,@@IDENTITY包含该语句生成的最后一个标识值。如果该语句不影响任何具有标识列的表,@@identity返回NULL

    我认为PERSON没有标识列,所以当您插入时,@@identity变为NULL

    如果要从其他表的insert中使用@标识,请使用它设置变量的值

    declare @PersistentID int;
    INSERT INTO bank.customer DEFAULT VALUES
    set @PersistentID = @@IDENTITY -- or scope_identity() is safer
    INSERT INTO bank.person (id,fname,lname)
      VALUES( @PersistentID ,'Mike','Phelps')
    

    通过不使用和使用
    范围\标识
    @@IDENTITY
    的值在这里是相同的吗?
    person
    account
    是否也有
    IDENTITY
    列?
    @@IDENTITY
    在使用时将为空。建议您仔细阅读如何使用上述所有列应具有相同的标识值是,Person表列ID应该从bank.customer表中获取值,该表只有ID列,account表的owner列也是如此-因此每次创建新帐户时,其ID都会通过数据库增加1。我建议使用
    SCOPE\u IDENTITY()
    而不是其他任何内容(如
    IDENT\u CURRENT()
    @@IDENTITY
    获取新插入的标识值。不要接受错误并将其转换为结果集。如果您实际上没有对错误执行任何有用的操作,则根本不要捕获错误-在回滚事务后重试它。顺便说一句,您错过了commit语句。因此,当两个批处理都
    插入
    bank.customer
    同时,在获取
    IDENT_CURRENT
    的值之前,您认为这里会发生什么?我想其他人需要理解区别,lol。
    IDENT_CURRENT
    @@identity
    相同。它在文档中告诉您,“最后生成的标识值可以用于任何会话和任何作用域。”我建议使用
    scope\u identity()
    而不是其他任何东西(如
    @@identity
    IDENT\u CURRENT
    )获取新插入的标识值。不同。因为当前标识用于特定表,而@标识用于所有表。因此不能在每句话中使用第二个标识。但是可以将@标识的值保存在变量中,并将其用于其他插入。尽管如此,@JoséIgnacioDurand仍然存在缺陷.如果两个插入同时发生(它们可以,也可以)
    IDENT_CURRENT
    将为两个会话提供最新的标识,而不管会话是什么,而不是该会话。竞争条件是一个问题,需要处理。这就是为什么
    SCOPE_identity
    在这里好得多的原因;它不会遇到这个问题。不要捕获并回滚,只需使用
    XACT_ABORT ON