我正在阅读关于将最后一个身份值输入数据库的不同方法的this回答。
根据我的理解,@@IDENTITY
通常是非常糟糕的主意,因为它可能会返回一个与您预期不同的标识 - 例如最近创建的标识值通过触发器。
但是如果您的代码在交易中会怎样?
例如,这是我正在做的事务的简化版本(使用ColdFusion):
<cftransaction>
<cfquery name="queryInsertA" datasource="source">
INSERT INTO tableA (columnName) VALUES (value)
</cfquery>
<cfquery name="queryInsertB" datasource="source">
INSERT INTO tableB (fkey_tableA, columnName) VALUES (@@IDENTITY, value)
</cfquery>
</cftransaction>
因为“If a transaction is successful, all of the data modifications made during the transaction are committed and become a permanent part of the database”,这是否意味着它还会阻止使用@@IDENTITY
时可能出现的问题?还是我误解了交易的行为?
答案 0 :(得分:14)
您链接的答案已经解释了@@IDENTITY
的主要问题:范围。如果您的插入触发另一个插入,您将获得意外的身份。交易不会改变任何内容。
答案 1 :(得分:2)
如果要将最后一个标识值插入表中,请使用Ident_current()函数。
Select ident_current ('your table name')
你也可以使用scope_identity(),它只会带来一个tablein的特定值。
Select scope_identity()
答案 2 :(得分:1)
您不需要@@ Identity,也不需要2个单独的查询。使用Scope_identity()函数实现完整性并使其成为同一连接的一部分。查询 - 就像这样。
<cfquery name="putUser" datasource="#dsn#">
SET NOCOUNT ON
INSERT INTO users(username, email)
VALUES
('#usersname#','#email#' )
SELECT SCOPE_IDENTITY() AS newId FROM users
SET NOCOUNT OFF
</cfquery>
<cfoutput>#putUser.newID#</cfoutput>
这将是完全安全的,但是像所有数据库事务一样,它仍然会遇到死锁,因此调整仍然很重要。
CFTRANSACTION适用于多个数据库操作,其中也可能涉及某些CF逻辑,但让数据库锁定和事务系统通过将它们保持在一起为您工作。
答案 3 :(得分:1)
您还可以使用result
的{{1}}属性。如果查询执行标识的INSERT或ID的自动增量值,则结构中将返回名为cfquery
的键。
GENERATEDKEY
请记住,这只是CF9及更高版本。
答案 4 :(得分:0)
您可以使用序列并在插入过程中使用它,如下所示:
CREATE SEQUENCE Testseq
START WITH 1
INCREMENT BY 1 ;
使用以下查询访问序列:
SELECT NEXT VALUE FOR Testseq;
答案 5 :(得分:0)
简化:
如果强>
你知道你在数据库系统中一无所有,这意味着,没有其他用户或进程在同一时间运行,没有其他事务在运行,你使用它时有绝对的ZERO活动,我的意思是它,ZERO ACTIVITY,那么,好吧......
<强> ELSE 强>
不,不!如果上面列出的任何内容确实在您的交易正在运行时发生,那么您最终会得到错误的身份。答案 6 :(得分:-2)
这取决于在事务实例化的同时运行的其他内容。如果与可以插入新标识值的事务无关的表上存在触发器,则您当前所在的事务范围将不会保护您。
例如,假设我创建了一个更新Table_A并在其中插入记录的SPROC。此表上有一个标识字段,每次插入新记录时,该字段将增加该表中的ID值。在我的SPROC中,我创建了一个事务并将我的插入放在事务中。插入后,我将@@ IDENTITY的值存储在同一事务中的变量中。
现在我还有另一个表Table_B,它有自己的标识值,但是这个表是触发器维护的。如果我正在执行我的SPROC以在Table_A中插入一行,并且在此更新期间Table_B也通过触发器更新,则当我检索@@ IDENTITY的值时,它实际上可能会给我创建的ID的值表_而不是Table_A。
您绝对应该在存储过程中使用事务,但最好选择插入的表的MAX(ID)来检索您创建的ID,而不是@@ IDENTITY。