我在使用触发器时遇到了众所周知的问题,并且@@IDENTITY
. 我创建了一个新的审计表和一个触发器以在其上插入审计行。我们使用的软件正在使用@@IDENTITY
,这导致与触发器插入新行时生成的 Id 发生冲突。我无法访问正在使用的代码@@IDENTITY
。
我需要关于如何自己产生身份价值的想法。我不能使用 GUID,因为订单对我很重要。如果我将 Id 列替换为具有默认值的 datetime 列GETDATE()
,它是否保证它是唯一的?
谢谢
我在使用触发器时遇到了众所周知的问题,并且@@IDENTITY
. 我创建了一个新的审计表和一个触发器以在其上插入审计行。我们使用的软件正在使用@@IDENTITY
,这导致与触发器插入新行时生成的 Id 发生冲突。我无法访问正在使用的代码@@IDENTITY
。
我需要关于如何自己产生身份价值的想法。我不能使用 GUID,因为订单对我很重要。如果我将 Id 列替换为具有默认值的 datetime 列GETDATE()
,它是否保证它是唯一的?
谢谢
GETDATE() 不会是唯一的。它的准确性使得可以同时提供多个近乎并发的事件。
如果您被迫生成自己的身份值,以免干扰@@IDENTITY,那么您可以执行以下操作...
INSERT INTO
myTable (
id,
field1,
field2
)
SELECT
(SELECT ISNULL(MAX(id), 0) FROM myTable WITH(TABLOCKX)) + 1,
@p1,
@p2
这隐含在它自己的事务中,并将保证唯一值。
编辑
我最初的评论是,这在插入多条记录时不起作用,相反,您需要单独遍历源记录,一次插入一条。
但是,以下示例可能适合您处理数据集...
WITH
sorted_data AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY field1) AS set_id, -- DO NOT include a PARTITION here
*
FROM
inserted
)
INSERT INTO
myTable (
id,
field1,
field2
)
SELECT
(SELECT ISNULL(MAX(id), 0) FROM myTable WITH(TABLOCKX)) + set_id,
@p1,
@p2
FROM
sorted_data
这将为每一行生成唯一的 ID,并且可以安全地防止使用相同代码的并发进程。
编辑
我已经添加WITH(TABLOCKX)
以防止其他进程在更新表时从表中读取。这可以防止并发进程建立相同的 MAX(id),然后尝试在新记录中插入重复的 id。
(单个查询结构已经阻止了记录在被读取后被更改,但没有阻止其他进程从“在”读取 MAX(id) 和插入所有新记录之间的表中读取。)
我知道您可能无法更改某些内容,但问题是该软件正在使用@@IDENTITY,这不在范围内。插入任何表都会更改@@IDENTITY。该软件应该使用函数 scope_identity() 代替。