结合 INSERT INTO 和 WITH/CTE

Posted

技术标签:

【中文标题】结合 INSERT INTO 和 WITH/CTE【英文标题】:Combining INSERT INTO and WITH/CTE 【发布时间】:2011-03-19 09:04:57 【问题描述】:

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

以下内容有效吗?

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

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

【问题讨论】:

【参考方案1】:

您需要先放置 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)

【讨论】:

【参考方案2】:

公用表表达式的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

几行样板代码使验证代码以正确的顺序插入正确数量的列变得非常容易,即使列数非常多。你未来的自己会在以后感谢你。

【讨论】:

这太棒了!突然之间,我不再那么讨厌 INSERT 语句了…… 这非常有用。对于在第一次阅读时错过它的任何其他人,这解决的问题是,在插入语句中,映射由要插入的字段的相对顺序和要插入的值定义,它们分别列出。如果您正常编写这些内容,则很难通过目视检查两个顺序是否相同。 CTE 允许您使用它们将要插入的列名称来命名值,这意味着您可以在两行上很好地对齐这些值。【参考方案3】:

是的:

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,语法以您为例。

【讨论】:

【参考方案4】:

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

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

插入到#stagetable执行(@InputSql)

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

【讨论】:

以上是关于结合 INSERT INTO 和 WITH/CTE的主要内容,如果未能解决你的问题,请参考以下文章

php mysql insert into 结合详解及实例代码

Oracle中insert into select和select into的区别

Oracle中insert into select和select into的区别

自增列和insert into的问题

Oracle中insert into select和select into的区别

VB insert into 的用法