web-dev-qa-db-ja.com

ID列に基づくT-SQL挿入値

Identity列に基づくPKを持つテーブルを作成することは可能ですか?

私が顧客のテーブルを持っているとしましょう。私たちのケースでは2つのフィールドが重要ですIdPKnvarchar(20)であり、SequenceIdintidentity(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
1
Jyrkka

値を取得する場所を指定していないので、SequenceIDは無効です。一時変数をもう1つ作成して、以下のようなものを追加することをお勧めします

@seqid intを宣言する

--seqidの@seqid = next値を選択シーケンスから
その後、シーケンスの代わりに、この変数を保持します

1
TheGameiswar

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)
)

必要に応じて、上の表のCustomerIDを主キーにできるはずです。 Sequenceの値は既に一意であるため(IDENTITYであるため)、複合主キーを作成する理由を質問します。これがあなたが望むデザインでよろしいですか?

4
Joel Brown

コードで値を計算するのではなく、計算列を検討してください。

ALTER TABLE dbo.Customers
    DROP COLUMN Id;

ALTER TABLE dbo.Customers
    ADD Id AS (CASE CustomerType WHEN 1 THEN N'P' ELSE N'x' END + CAST((SequenceId + 1000000) AS nvarchar(10)));

以下は、この計算された列を使用した挿入プロシージャの例です。

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

INSERT  INTO [dbo].[Customers]
        ( [GivenName]
        , [Surname]
        , [BirthDate]
        )
OUTPUT  inserted.Id
VALUES  ( @GivenName
        , @Surname
        , @BirthDate
        );
GO

編集:列の永続化に関するコメントを削除しました。

2
Dan Guzman

identityフィールドは、代理キーフィールドであることを意図しています。 PKであるという事実は、一意性を保証するものであり、必ずしもアイデンティティ自体を保証するものではありません。サロゲートキーの値を割り当てる意味はありません。つまり、テーブルに挿入されたときのシーケンスでさえ、関連する行については何も想定できません。つまり、ID 1000がID 1001の前にテーブルに挿入されたと想定しないでください。

@Joel Brownによって提案されたprefixフィールドなどの他のフィールドには、追加の意味を配置する必要があります。管理reallyがプレフィックスとIDの値を結合したい場合は、レポートで確認してください。設計に組み込まないでください。あなたは将来のために大きな頭痛の種で設計します。

また、identityフィールドを定義して、すべてのクエリに追加するのではなく、1000000から開始することもできます。

0
TommCatt