web-dev-qa-db-ja.com

INSERT INTOとWITH / CTEの組み合わせ

非常に複雑なCTEがあり、結果を物理テーブルに挿入したいと思います。

以下は有効ですか?

INSERT INTO dbo.prf_BatchItemAdditionalAPartyNos 
(
    BatchID,
    AccountNo,
    APartyNo,
    SourceRowID
)       
WITH tab (
  -- some query
)    
SELECT * FROM tab

関数を使用してこのCTEを作成し、再利用できるようにすることを考えています。何かご意見は?

142
dcpartners

CTEを最初に配置してから、INSERT INTOをselectステートメントと組み合わせる必要があります。また、CTEの名前に続く「AS」キーワードはオプションではありません。

WITH tab AS (
    bla bla
)
INSERT INTO dbo.prf_BatchItemAdditionalAPartyNos (
BatchID,
AccountNo,
APartyNo,
SourceRowID
)  
SELECT * FROM tab

コードは、CTEが正確に4つのフィールドを返すこと、およびこれらのフィールドがINSERTステートメントで指定されたフィールドと順序およびタイプが一致することを前提としていることに注意してください。そうでない場合は、「SELECT *」を必要なフィールドの特定の選択に置き換えてください。

関数の使用に関する質問については、「依存します」と言います。パフォーマンス上の理由だけでデータをテーブルに入れており、関数を介してデータを使用するときに速度が許容できる場合、関数はオプションであると考えます。一方、複数の異なるクエリでCTEの結果を使用する必要があり、速度がすでに問題になっている場合は、テーブル(通常または一時)を選択します。

WITH common_table_expression(Transact-SQL)

244

うん:

WITH tab (
  bla bla
)

INSERT INTO dbo.prf_BatchItemAdditionalAPartyNos (  BatchID,                                                        AccountNo,
APartyNo,
SourceRowID)    

SELECT * FROM tab

これは、複数のCTEをサポートするSQL Server用です。

WITH x AS (), y AS () INSERT INTO z (a, b, c) SELECT a, b, c FROM y

Teradataでは1つのCTEのみが許可されており、構文は例のとおりです。

16
Cade Roux

共通テーブル式のWITH句は先頭にあります。

CTEですべての挿入をラップすると、クエリロジックを列マッピングから視覚的に分離できるという利点があります。

間違いを見つける:

WITH _INSERT_ AS (
  SELECT
    [BatchID]      = blah
   ,[APartyNo]     = blahblah
   ,[SourceRowID]  = blahblahblah
  FROM Table1 AS t1
)
INSERT Table2
      ([BatchID], [SourceRowID], [APartyNo])
SELECT [BatchID], [APartyNo], [SourceRowID]   
FROM _INSERT_

同じ間違い:

INSERT Table2 (
  [BatchID]
 ,[SourceRowID]
 ,[APartyNo]
)
SELECT
  [BatchID]      = blah
 ,[APartyNo]     = blahblah
 ,[SourceRowID]  = blahblahblah
FROM Table1 AS t1

ボイラープレートの数行により、非常に多数の列がある場合でも、コードが正しい順序で正しい数の列を挿入することを非常に簡単に確認できます。あなたの将来の自己は後であなたに感謝します。

16
Anon