我遇到了一个众所周知的触发器问题和@@ IDENTITY。 我创建了一个新的审核表和一个触发器,用于在其上插入审核行。 我们使用的是使用@@ IDENTITY的软件,这会导致与触发器插入新行时生成的Id发生冲突。 我无法访问使用@@ IDENTITY的代码。
我需要关于如何通过自己生成身份价值的想法。我不能使用GUID,因为订单对我很重要。 如果我用默认值GETDATE()的datetime列替换Id列,它是否保证它是唯一的?
谢谢
答案 0 :(得分:2)
GETDATE()不会是唯一的。它的准确性使得可以同时提供多个近似并发事件。
如果您强制生成自己的身份值,以免干扰@@ IDENTITY,那么您可以执行以下操作...
INSERT INTO
myTable (
id,
field1,
field2
)
SELECT
(SELECT ISNULL(MAX(id), 0) FROM myTable WITH(TABLOCKX)) + 1,
@p1,
@p2
这隐含在它自己的交易中,并将保证唯一的价值。
修改强>
我原来的评论是,当插入多个记录时,这将无效,而您需要单独遍历源记录,一次插入一个。
但是,以下示例可能适合您处理数据SET ...
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)和插入的所有新记录之间的表中读取。)
答案 1 :(得分:1)
我知道您可能无法更改内容,但问题是该软件使用的是@@ IDENTITY,这不在范围内。插入任何表格将更改@@ IDENTITY。该软件应该使用函数scope_identity()代替。