次のようなサンプル テーブルを使用します。
CREATE TABLE MyTable (id INT IDENTITY(1,1), someCol NVARCHAR(20), codeCol NVARCHAR(20))
id 列、ランダムな値の列、およびコードが格納される 3 番目の列があります。
トリガーは次のようになります。
CREATE TRIGGER tgInsertMyTable ON myTable
AFTER INSERT
AS
BEGIN
DECLARE @code NVARCHAR(20)
SELECT @code = 'ABC-' + CAST(YEAR(GETDATE()) AS NVARCHAR(4)) + '-'
DECLARE @max NVARCHAR(20)
SELECT @max = codeCol FROM dbo.myTable mts WHERE mts.codeCol LIKE @code + '%'
;WITH CTE_UPD AS
(
SELECT REPLICATE('0', 5-LEN(CAST(COALESCE(CAST(RIGHT(@max,5) AS INT),0) + ROW_NUMBER() OVER (ORDER BY ins.ID) AS NVARCHAR(5)))) + CAST(COALESCE(CAST(RIGHT(@max,5) AS INT),0) + ROW_NUMBER() OVER (ORDER BY ins.ID) AS NVARCHAR(5)) AS nextNo, id
FROM INSERTED ins
)
UPDATE mt
SET mt.CodeCol = @code + nextNo
FROM dbo.MyTable mt
INNER JOIN CTE_UPD ins ON ins.ID = mt.ID
END
いくつかの場所で複雑に見えることはわかっているので、少し説明しようと思いますが、最初に、適切に動作するデモを次に示します。
SQLFiddle デモ
そのため、最初に変数に目的のコード プレフィックスを設定し@code
ます。これはインクリメントのない部分です。
2番目-テーブル内の既存の行で同じ接頭辞を持つ最大値を検索し、それを変数に保存します@max
3 番目の部分は CTE です。次の増分値を見つけるために使用されます。
- 最大値から最後の 5 文字のみを取り除く (RIGHT 関数)
- それらを int に変換します (CAST) - 開始ゼロから削除します
- @max が NULL の場合 - 現在は 0 と宣言されています (COALESCE)
- 挿入された ROW_NUMBER を追加します - これは重要です - 同時に複数の行を追加する可能性があるため (デモのように)、+1 だけを使用することはできません。これが、そもそも CTE が必要な理由です。
- nvarchar にキャストバック
- REPLICATE は、5-LEN の量の開始ゼロを返すために使用されます (数値が 10、100、1000 になると、より少ないゼロを追加するために新しい LEN が計算されます)。
最後に、CTE をテーブルに結合し、@code + 計算値で更新するだけです
もっと簡単な解決策があるかもしれないが、これが機能するかどうかはわかりません-そして、すべてのシナリオをカバーしていると思います。