【问题标题】:Creating primary key with a static element and an auto-incrementing element without making a composite primary key使用静态元素和自动递增元素创建主键,而不创建复合主键
【发布时间】:2021-11-02 05:29:55
【问题描述】:

问题

我有两张桌子。两者都将具有自动递增的ID 列,这些列将充当它们各自的主键列。

表 1 的 ID 列从 1 开始自动递增,每个条目递增 1。作为参考,我为此使用了IDENTITY (1,1)

我希望表二的 ID 列的行为方式相同,但也具有静态文本/数字前缀,即 M1、M2、M3 或 M00001、M00002、M00003 等。

我发现的所有资源似乎都涉及到复合主键的使用;我想避免这种情况。

其他信息

从我的阅读中我得到的印象是,这种方法可能不是区分数据库中多个表的主键的最佳或正确方法,但是,我正在努力寻找最好的资源/示例或最常见的方法来做到这一点。我已经探索过使用复合键、计算字段、UUID、Hi/Lo 算法 id,但我不确定什么是正确的继续方式。就上下文而言,这不是一个庞大或复杂的数据库。

即使只是一个关于这个问题的好资源的链接也会对我有很大帮助。

【问题讨论】:

  • 您想使用“M1”创建密钥的原因是什么?解释您对此的要求将有助于人们就正确的解决方案提出建议。显而易见的答案是,绝对不要将此作为任何类型的键,而是使用计算列。
  • 您是否有特殊原因要区分这些键?通常的想法是,合成键(不属于您存储的数据的一部分)通常不应该有任何意义/特殊特征,除了对每一行都是唯一的并且没有空值。
  • 这种由部件构成的“智能标识符”是一种反模式。但是您可以使用包含您的身份 PK 作为备用键的唯一计算列或唯一列集。不过,没有理由避免使用复合键。您可能应该发布一个问题,说明您是如何被困在自己想做的事情上的。
  • 我强烈主张将主键留在ID INT IDENTITY 列上,而不是让您的“字母数字”列成为PK。 INT 更小,它是一个数值,因此不容易出现拼写错误、尾随空格、排序规则问题等等。您可以拥有一个计算列,将您的 ID 列转换为您需要的格式 - 但不要将其作为 PK!
  • 这闻起来像XY problem。如果您的标识符列在其表中是唯一的,那么向其添加静态前缀不会使其 more 唯一。我猜您正在尝试将 两个表中的任何一个 中的值存储在相关表的单个列中,然后使用同一列连接到两个表 - 期望只有一个“工作” .

标签: sql sql-server database tsql primary-key


【解决方案1】:

在第二个表中,您可以保留它并添加带有计算值的第二列,而不是修改索引。下面是表格中此类字段的完整示例(我使用的是表格变量,但在普通表格中看起来相同)。

declare @tab as table 
(
    id int primary key identity(1, 1),
    id2 as concat('M', format(id, '00000#')),
    someColumn nvarchar(10)
)

insert into @tab (someColumn) values
(N'test 1'), ('test 2'), (N'test 3');

select * from @tab;

最后一个查询的结果是

如您所见,id2 是根据id 索引的值自动计算的。

如果您想存储id2,则必须通过添加 PERSISTED 来修改表格,如下面的代码所示

declare @tab as table 
(
    id int primary key identity(1, 1),
    id2 as concat('M', format(id, '00000#')) PERSISTED,
    someColumn nvarchar(10)
)

您可以找到更多关于计算列的信息here

【讨论】:

    【解决方案2】:

    没有合适的解决方案。

    但是可以使用下面的查询

    IF Not Exists(Select * From sys.tables t where t.name='ids')
    Begin
        Create Table ids(id int)
        Insert into ids values(0)
    End
    Go
    IF Not Exists(Select * From sys.tables t where t.name='tbltextIdentity')
    Create Table tbltextIdentity (id  varchar(50) primary key ,someColumn nvarchar(10))
    Go
    --insert into tbltextIdentity values('M000001','Test1')
    UPDATE Ids SET  Id = id +1 OUTPUT concat('M', format(INSERTED.Id, '00000#')), 'Test1' INTO tbltextIdentity 
    Go
    Select * From tbltextIdentity
    

    【讨论】:

      猜你喜欢
      • 2012-04-16
      • 2014-01-17
      • 2017-10-14
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多