Menggabungkan INSERT INTO dan WITH / CTE

157

Saya memiliki CTE yang sangat kompleks dan saya ingin memasukkan hasilnya ke dalam tabel fisik.

Apakah yang berikut ini valid?

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

Saya berpikir untuk menggunakan fungsi untuk membuat CTE ini yang memungkinkan saya untuk menggunakan kembali. Adakah pikiran?

mitra pendamping
sumber

Jawaban:

271

Anda harus mengutamakan CTE dan kemudian menggabungkan INSERT INTO dengan pernyataan pilihan Anda. Juga, kata kunci "AS" yang mengikuti nama CTE bukan opsional:

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

Harap perhatikan bahwa kode mengasumsikan bahwa CTE akan mengembalikan tepat empat bidang dan bidang-bidang tersebut sesuai dengan urutan dan jenis dengan yang ditentukan dalam pernyataan INSERT. Jika bukan itu masalahnya, ganti saja "SELECT *" dengan bidang tertentu yang Anda butuhkan.

Adapun pertanyaan Anda tentang menggunakan fungsi, saya akan mengatakan "itu tergantung". Jika Anda meletakkan data dalam tabel hanya karena alasan kinerja, dan kecepatannya dapat diterima saat menggunakannya melalui suatu fungsi, maka saya akan menganggap fungsi sebagai pilihan. Di sisi lain, jika Anda perlu menggunakan hasil CTE di beberapa pertanyaan berbeda, dan kecepatan sudah menjadi masalah, saya akan memilih tabel (baik reguler, atau temp).

DENGAN common_table_expression (Transact-SQL)

Valentino Vranken
sumber
19

The WITHklausul untuk Common Table Expressions pergi di bagian atas.

Membungkus setiap sisipan dalam CTE memiliki manfaat memisahkan secara visual logika kueri dari pemetaan kolom.

Temukan kesalahan:

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_

Kesalahan yang sama:

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

Beberapa baris boilerplate membuatnya sangat mudah untuk memverifikasi kode yang memasukkan jumlah kolom yang tepat dalam urutan yang benar, bahkan dengan jumlah kolom yang sangat besar. Masa depan Anda akan berterima kasih nanti.

Segera
sumber
3
Ini bagus! Tiba-tiba, saya tidak terlalu membenci pernyataan INSERT ...
NReilingh
1
Ini sangat berguna. Untuk siapa pun yang melewatkannya pada bacaan pertama, masalah yang dipecahkan ini adalah bahwa dalam pernyataan penyisipan pemetaan didefinisikan oleh urutan relatif bidang yang akan dimasukkan ke dalam dan nilai yang akan dimasukkan ke dalamnya, yang didaftar secara terpisah. Jika Anda menulis ini secara normal, sangat sulit untuk memeriksa dengan inspeksi visual bahwa kedua pemesanannya sama. CTE memungkinkan Anda memberi nama nilai dengan nama kolom yang akan dimasukkan, yang berarti Anda dapat menyelaraskannya dengan sangat baik pada dua baris.
Tidorith
16

Ya:

WITH tab (
  bla bla
)

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

SELECT * FROM tab

Perhatikan bahwa ini untuk SQL Server, yang mendukung beberapa CTE:

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

Teradata hanya mengizinkan satu CTE dan sintaksnya adalah sebagai contoh Anda.

Cade Roux
sumber