SQL 服务器自定义标识列
SQL Server Custom Identity Column
我想生成一个与产品类型相关的自定义标识列。
这个查询能不能保证身份的顺序,解决并发问题。
这是一个示例查询:
BEGIN TRAN
INSERT INTO TBLKEY
VALUES((SELECT 'A-' + CAST(MAX(CAST(ID AS INT)) + 1 AS NVARCHAR) FROM TBLKEY),'EHSAN')
COMMIT
这将是一件坏事,因为无法保证两个查询 运行 同时获得的 MAX(ID) 不会是相同的值。
如果您使用标准标识列,您还可以有一个使用该列的计算列,或者在您 return 数据时仅使用 return 键。
埃德
试试这个:
BEGIN TRAN
INSERT INTO TBLKEY
VALUES((SELECT MAX(ID) + 1 AS NVARCHAR) FROM TBLKEY WITH (UPDLOCK)),'EHSAN')
COMMIT
选择最大 ID 时,您将获得该行的 U 锁。 U 锁与 U 锁不兼容,后者将尝试同时获取具有相同查询 运行ning 的另一个会话。在给定时间只会执行一个查询。 id 将有序且连续,它们之间没有任何间隙。
更好的解决方案是创建一个额外的 table 专用于存储当前或下一个 ID 并使用它而不是最大值。
您可以通过执行以下操作了解差异:
准备一个table
CREATE TABLE T(id int not null PRIMARY KEY CLUSTERED)
INSERT INTO T VALUES(1)
然后运行下面的查询在两个不同的session中一个接一个,相隔不到10秒
BEGIN TRAN
DECLARE @idv int
SELECT @idv = max (id) FROM T
WAITFOR DELAY '0:0:10'
INSERT INTO T VALUES(@idv+1)
COMMIT
稍等片刻,直到两个查询都完成。观察其中一个成功,另一个失败。
现在对以下查询执行相同的操作
BEGIN TRAN
DECLARE @idv int
SELECT @idv = max (id) FROM T WITH (UPDLOCK)
WAITFOR DELAY '0:0:5'
INSERT INTO T VALUES(@idv+1)
COMMIT
查看T的内容
用 DROP TABLE T
清理 T Table
我想生成一个与产品类型相关的自定义标识列。 这个查询能不能保证身份的顺序,解决并发问题。 这是一个示例查询:
BEGIN TRAN INSERT INTO TBLKEY VALUES((SELECT 'A-' + CAST(MAX(CAST(ID AS INT)) + 1 AS NVARCHAR) FROM TBLKEY),'EHSAN') COMMIT
这将是一件坏事,因为无法保证两个查询 运行 同时获得的 MAX(ID) 不会是相同的值。
如果您使用标准标识列,您还可以有一个使用该列的计算列,或者在您 return 数据时仅使用 return 键。
埃德
试试这个:
BEGIN TRAN
INSERT INTO TBLKEY
VALUES((SELECT MAX(ID) + 1 AS NVARCHAR) FROM TBLKEY WITH (UPDLOCK)),'EHSAN')
COMMIT
选择最大 ID 时,您将获得该行的 U 锁。 U 锁与 U 锁不兼容,后者将尝试同时获取具有相同查询 运行ning 的另一个会话。在给定时间只会执行一个查询。 id 将有序且连续,它们之间没有任何间隙。
更好的解决方案是创建一个额外的 table 专用于存储当前或下一个 ID 并使用它而不是最大值。
您可以通过执行以下操作了解差异:
准备一个table
CREATE TABLE T(id int not null PRIMARY KEY CLUSTERED)
INSERT INTO T VALUES(1)
然后运行下面的查询在两个不同的session中一个接一个,相隔不到10秒
BEGIN TRAN
DECLARE @idv int
SELECT @idv = max (id) FROM T
WAITFOR DELAY '0:0:10'
INSERT INTO T VALUES(@idv+1)
COMMIT
稍等片刻,直到两个查询都完成。观察其中一个成功,另一个失败。
现在对以下查询执行相同的操作
BEGIN TRAN
DECLARE @idv int
SELECT @idv = max (id) FROM T WITH (UPDLOCK)
WAITFOR DELAY '0:0:5'
INSERT INTO T VALUES(@idv+1)
COMMIT
查看T的内容
用 DROP TABLE T