web-dev-qa-db-ja.com

T-SQL、サブクエリのMAX()+ 1で挿入がインクリメントされない、代替?

IDのない主キーを使用してテーブルに行を「バッチ」挿入する必要があるクエリがあります。

--TableA
--PK int (Primary key, no-identity)
--CustNo int
INSERT INTO TableA (PK,CustNo)
  SELECT (SELECT MAX(PK)+1 AS PK FROM TableA), CustNo
  FROM Customers

(簡略化された例-同時実行の問題の可能性についてコメントしないでください:-))

問題は、処理された行ごとにPKがインクリメントされず、主キー違反が発生することです。

カーソル/ whileループでそれを行う方法を知っていますが、それを避け、可能であれば、セットベースの方法で解決したいと思いますか?

(SQL Server 2008 Standardの実行)

13
KorsG
Declare @i int;

Select @i = max(pk) + 1 from tablea;

INSERT INTO TableA (PK, custno)
Select row_number() over(order by custno) + @i  , CustNo
FROM Customers
25
Michael Buen

Michael Buenに+1しますが、1つの提案があります。

テーブル「tablea」は空にすることができるので、次のように書く必要があります。

Select @i = isnull(max(pk),0) + 1 from tablea;

これにより、このコードを使用しようとしたときにnullエラーが発生するのを防ぐことができます。

7
Max

あなたが見てきたように問題は、それらがすべて同じ行番号を取得することです。max(PK)+1はすべての行で同じです。

Max(PK) + Row_number()に変換してみてください

私は、これが悪い考えであるとあなたが知っている理由などに基づいて取り組んでいます。あなたの質問は、問題をどのように解決したいかではなく、答えを得るために簡略化されています。

4
Andrew

あなたはできる;

;with T(NPK, CustNo) as (
  select row_number() over (order by CustNo), CustNo from Customers
)
insert into TableA (PK, CustNo)
  select NPK, custno from T
order by CustNo 
3
Alex K.

私はあなたの相棒に提案があります、SQLのより良い練習はSEQUENCEを使用することを言います、そして何を推測するか、それは人がそれをするのは非常に簡単です、ただ私のものをコピーして貼り付けてください:

CREATE SEQUENCE SEQ_TABLEA AS INTEGER START WITH 1 INCREMENT BY 1 MAXVALUE 2147483647 MINVALUE 1 NO CYCLE

そしてこのように使用します:

TableA(PK、CustNo)の値に挿入(SEQ_TABLEA.NEXTVAL、123)

このヒントがあなたを助けることができることを願っています!

1