【问题标题】:SQL Server Custom Identity ColumnSQL Server 自定义标识列
【发布时间】:2015-04-29 07:46:29
【问题描述】:

我想生成一个与产品类型相关的自定义标识列。 该查询能否保证身份的顺序并解决并发问题。 这是一个示例查询:

开始传输 插入到 TBLKEY 值((选择'A-'+ CAST(MAX(CAST(ID AS INT))+ 1 AS NVARCHAR)来自TBLKEY),'EHSAN') 犯罪

【问题讨论】:

  • 尝试使用序列而不是 +1。
  • @DudiKonfino,我不能使用身份或序列和计算字段,因为数字的连续性与产品类型有关,例如 10001 productA, 20001 productB
  • 您可以从 10001 开始和 10000 步创建
  • 您似乎认为您的集合需要是连续的。这是一个常见的错误信念。也就是说,除了 ID 空间看起来很漂亮之外,您还有什么商业原因?使用 SQL Server 为您提供的工具(即标识列或序列值),让您的生活变得更轻松。

标签: sql-server concurrency identity


【解决方案1】:

试试这个:

BEGIN TRAN

INSERT INTO TBLKEY
VALUES((SELECT MAX(ID) + 1 AS NVARCHAR) FROM TBLKEY WITH (UPDLOCK)),'EHSAN')

COMMIT

在选择最大ID时,您可以在行上获取U锁定。 U 锁与 U 锁不兼容,U 锁将尝试获取同时运行相同查询的另一个会话。在给定时间只会执行一个查询。 id 将有序且连续,它们之间没有任何间隙。

更好的解决方案是创建一个额外的表,专门用于存储当前或下一个 id,并使用它而不是最大值。

您可以通过执行以下操作来了解区别:

准备一张桌子

CREATE TABLE T(id int not null PRIMARY KEY CLUSTERED)
INSERT INTO T VALUES(1)

然后在两个不同的会话中一个接一个地运行以下查询,间隔不到 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表

【讨论】:

  • 谢谢,我只测试了您在两个不同事务中所说的 Select 语句并且工作正常。
  • 它可能会工作并且没有 UPDLOCK 但它是不正确的。
  • 使用 UPDLOCK 我也可以将新 id 放入变量中并在 Insert 语句中使用它:BEGIN TRAN DECLARE @NEWID AS NVARCHAR SET @NEWID = (SELECT MAX(ID) + 1 AS NVARCHAR) FROM TBLKEY WITH (UPDLOCK)) INSERT INTO TBLKEY VALUES(@NEWID,'EHSAN') COMMIT 对吗?
  • 非常感谢。很有帮助。
【解决方案2】:

这将是一件坏事,因为无法保证同时运行的两个查询不会将 MAX(ID) 设为相同的值。

如果您使用标准标识列,您还可以有一个使用该标识列的计算列,或者在返回数据时只返回键。

埃德

【讨论】:

  • 如果他将查询更改为 FROM TBLKEY WITH (UPDLOCK),他可以进行尝试。这样,同时运行的两个查询无法获得相同的 MAX(ID),其中一个将被另一个阻止。此外,我认为生成的 id 不仅会按升序排列,而且还会连续。这种方式的缺点是所有并行查询都是序列化的。
  • 更不用说 CAST(ID AS INT) 的形式是 CAST('A-XXXX') 会失败。
  • @Ed Elliot,我不能使用身份和计算字段,因为数字的连续性与产品类型有关,例如 10001 productA, 20001 productB。
  • @Blim,我知道上面的 CAST 有错误,但我说这只是一个示例。
  • @Ehsan 我明白了,但我想提一下以供将来参考。试试 UPDLOCK 提示,你可以找到更多关于它的信息here
猜你喜欢
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 2016-07-07
  • 2013-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多