Поєднання INSERT INTO та WITH / CTE


157

У мене дуже складний CTE, і я хотів би вставити результат у фізичну таблицю.

Чи дійсне наступне?

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

Я думаю про використання функції для створення цього CTE, який дозволить мені повторно використовувати. Будь-які думки?

Відповіді:


271

Спершу потрібно поставити CTE, а потім поєднати INSERT INTO із вашим оператором select. Крім того, ключове слово "AS" після імені CTE не є обов'язковим:

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

Зверніть увагу, що код передбачає, що CTE поверне рівно чотири поля і що ці поля відповідають за порядком і типом з тими, які вказані в операторі INSERT. Якщо це не так, просто замініть "ВИБІР *" конкретним вибором потрібних полів.

Щодо вашого питання щодо використання функції, я б сказав "це залежить". Якщо ви заносите дані в таблицю тільки з причин продуктивності, а швидкість прийнятна при використанні їх через функцію, то я вважаю функцію опцією. З іншого боку, якщо вам потрібно використовувати результат CTE в декількох різних запитах, а швидкість - це вже проблема, я б пішов за таблицю (або звичайну, або тимчасову).

З common_table_expression (Transact-SQL)


19

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

Кілька рядків котлоагрегату надзвичайно легко перевірити, чи код вставляє потрібну кількість стовпців у потрібному порядку, навіть при дуже великій кількості стовпців. Ваша майбутня власна пізніше вам подякує.


3
Це чудово! Раптом я не так ненавиджу заяви INSERT ...
NReilingh

1
Це надзвичайно корисно. Для всіх, хто пропустив це в першому читанні, проблема, яку це вирішує, полягає у тому, що в операторі вставки відображення визначається відносним упорядкуванням полів, які потрібно вставити, та значень, які потрібно вставити в них, які перераховані окремо. Якщо ви пишете їх зазвичай, надзвичайно складно перевірити візуальним оглядом, що два замовлення однакові. CTE дозволяє називати значення назвами стовпців, в які вони збираються вставити, а це означає, що ви можете вирівняти їх по-справжньому в двох рядках.
Тідоріт

16

Так:

WITH tab (
  bla bla
)

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

SELECT * FROM tab

Зауважте, що це стосується SQL Server, який підтримує декілька CTE:

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

Teradata дозволяє лише один CTE, і синтаксис є вашим прикладом.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.