Сочетание INSERT INTO и WITH / CTE

157

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

Является ли следующее действительным?

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

Я думаю об использовании функции для создания этого CTE, который позволит мне использовать повторно. Есть предположения?

dcpartners
источник

Ответы:

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. Если это не так, просто замените «SELECT *» определенным выбором полей, которые вам нужны.

Что касается вашего вопроса об использовании функции, я бы сказал «это зависит». Если вы помещаете данные в таблицу только из-за соображений производительности, и скорость является приемлемой при использовании их через функцию, тогда я считаю, что функция является опцией. С другой стороны, если вам нужно использовать результат CTE в нескольких разных запросах, а скорость уже является проблемой, я бы выбрал таблицу (обычную или временную).

WITH 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, и синтаксис в качестве вашего примера.

Кейд Ру
источник