将INSERT INTO和WITH / CTE结合


157

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

以下有效吗?

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

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

Answers:


271

您需要先放置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的结果,而速度已经是一个问题,我将选择一个表(常规表或临时表)。

带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允许您使用要插入的列名称来命名值,这意味着您可以将它们很好地对齐在两行上。
Tidorith

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,并且语法示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.