T-SQL 基于标识列插入值

Jyr*_*kka 2 database-design sql-server dml t-sql

是否可以有一个基于 Identity 列的具有 PK 的表?

假设我有一个客户表,两个字段对于我们的案例很重要,Id即 isPK nvarchar(20)SequenceIdwhich is int identity(1,1)。我想要一个存储过程,该过程将具有(除其他外)一个参数@CustomerType,并根据此参数生成值Id并将新行插入表中。像这样的东西:

CREATE PROCEDURE createCustomer
@CustomerType int, 
@GivenName nvarchar(20), 
@Surname nvarchar(20), 
@BirthDate date = null
...
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @prefix nvarchar(1) = N'x'
    IF @CustomerType = 1
    BEGIN
        SET @prefix = N'P'
    END
...
    ELSE
    BEGIN
        SET @prefix = N'x'
    END

    INSERT INTO [dbo].[Customers]
           ([Id],
            [GivenName],[Surname],[BirthDate])
    VALUES
           (@prefix + (SequenceId + 1000000),
        @GivenName,@Surname,@BirthDate);

    SELECT INSERTED.Id AS CustomerId;
END
Run Code Online (Sandbox Code Playgroud)

Joe*_*own 5

你从来没有设置过SequenceId任何东西。在插入期间,无法使用引用同一表上 IDENTITY 列值的表达式来设置列的值,该表将在同一插入操作中设置该值。如果您考虑一下,这是有道理的,因为该行在插入之前并不存在,因此在插入开始时没有 IDENTITY 值。

如果您想要创建一个连接前缀和 IDENTITY 值的列,那么您应该使用计算列,例如:

CREATE TABLE dbo.Customers
( Sequence   int  IDENTITY(1,1) NOT NULL
, Prefix     nchar(1) NOT NULL
, CustomerID AS Prefix + CAST(Sequence + 1000000 as nvarchar(8))
, GivenName  nvarchar(50)
... etc ... 
, CONSTRAINT UN_CustomersSequence UNIQUE (Sequence)
, CONSTRAINT PK_Customers PRIMARY KEY (CustomerID)
)
Run Code Online (Sandbox Code Playgroud)

如果需要,您应该能够CustomerID在上表中设置主键。由于该Sequence值已经是唯一的(由于是 IDENTITY),我会质疑为什么要创建复合主键。你确定这是你想要的设计吗?

  • “IDENTITY”属性不强制唯一性(例如重新播种、身份插入),您需要一个唯一的约束或索引。 (2认同)
  • 如果对我和你来说可能是“显而易见的”,但你当前的答案措辞很容易被误解:“因为序列值已经是唯一的(由于是 IDENTITY)”。我最初的评论是鼓励您编辑答案以澄清。毕竟,这是一个常见的误解。 (2认同)