结合INSERT INTO和WITH / CTE

时间:2010-07-22 05:48:44

标签: tsql insert common-table-expression

我有一个非常复杂的CTE,我想将结果插入物理表。

以下是否有效?

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

我正在考虑使用一个函数来创建这个允许我重用的CTE。有什么想法吗?

4 个答案:

答案 0 :(得分:244)

您需要先放置CTE,然后将INSERT INTO与select语句结合使用。此外,CTE名称后面的“AS”关键字不是可选的:

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)

答案 1 :(得分:16)

是的:

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只允许一个CTE,语法就是你的例子。

答案 2 :(得分:16)

Common Table Expressions的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 :(得分:0)

迟到了,但出于我的目的,我希望能够运行用户输入的代码并存储在临时表中。使用 oracle 没有这样的问题.. 插入是在 with 子句之前的语句的开头。

为了在 sql server 中工作,以下工作:

INSERT into #stagetable execute (@InputSql)

(所以选择语句@inputsql 可以作为 with 子句开始)。