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、帐户、类型]
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