【问题标题】:Update records in table from CTE从 CTE 更新表中的记录
【发布时间】:2012-07-18 17:42:21
【问题描述】:

我有以下 CTE,它将为我提供整个发票的 DocTotal。

 ;WITH CTE_DocTotal
 AS
 (
   SELECT SUM(Sale + VAT) AS DocTotal
   FROM PEDI_InvoiceDetail
   GROUP BY InvoiceNumber
 )

UPDATE PEDI_InvoiceDetail
SET DocTotal = CTE_DocTotal.DocTotal

现在有了这个结果,我想在列中输入 PEDI_InvoiceDetail 中的 DocTotal 值。

我知道这行不通,我知道我错过了什么,这是什么?

【问题讨论】:

  • 我选择了 CTE 选项以获得更好的性能。

标签: sql sql-server tsql common-table-expression


【解决方案1】:

你不需要 CTE 来做这个

UPDATE PEDI_InvoiceDetail
SET
    DocTotal = v.DocTotal
FROM
     PEDI_InvoiceDetail
inner join 
(
   SELECT InvoiceNumber, SUM(Sale + VAT) AS DocTotal
   FROM PEDI_InvoiceDetail
   GROUP BY InvoiceNumber
) v
   ON PEDI_InvoiceDetail.InvoiceNumber = v.InvoiceNumber

【讨论】:

  • @Zack SQL 中的“正确性”和“可读性”在某种程度上是主观的并且是个人喜好问题。但是,某些历史版本的 SQL Server 不包含 CTE 功能。
  • @HolgerJakobs 这个问题是关于 SQL Server 的。 SQLite 会有自己的语法
  • 问题是关于如何从 CTE 更新记录,而不是关于替代方法。 OP 可能想要使用 CTE 的原因有几个,但问题中没有透露。
  • @DerekGreer OP 说“我想在列中输入 PEDI_InvoiceDetail 中的 DocTotal 值。”他没有说他需要或想一定要使用 CTE。
  • 正确,除了他在标题中总结了他的问题:“从 CTE 更新表中的记录”。作为证据,我正在阅读 OP 对涉及 CTE 的答案的渴望,我提交作为证据证明他接受了使用 CTE 提供解决方案的答案,并且他在后续评论中表示他选择 CTE 是为了表现。
【解决方案2】:
WITH CTE_DocTotal (DocTotal, InvoiceNumber)
AS
(
    SELECT  InvoiceNumber,
            SUM(Sale + VAT) AS DocTotal
    FROM    PEDI_InvoiceDetail
    GROUP BY InvoiceNumber
)    
UPDATE PEDI_InvoiceDetail
SET PEDI_InvoiceDetail.DocTotal = CTE_DocTotal.DocTotal
FROM CTE_DocTotal
INNER JOIN PEDI_InvoiceDetail ON ...

【讨论】:

    【解决方案3】:

    您对 CTE 所做的更新将级联到源表。

    我不得不稍微猜测一下您的架构,但这样的事情应该可以工作。

    ;WITH T AS
    (   SELECT  InvoiceNumber, 
                DocTotal, 
                SUM(Sale + VAT) OVER(PARTITION BY InvoiceNumber) AS NewDocTotal
        FROM    PEDI_InvoiceDetail
    )
    UPDATE  T
    SET     DocTotal = NewDocTotal
    

    【讨论】:

    • CTE UPDATE 是原子的,如果运行并发查询,相同的记录会更新两次吗?
    • CTE 更新与普通更新没有什么不同。它是原子的,将采用相同的表/行锁。它只不过是语法糖
    【解决方案4】:

    尝试以下查询:

    ;WITH CTE_DocTotal
     AS
     (
       SELECT SUM(Sale + VAT) AS DocTotal_1
       FROM PEDI_InvoiceDetail
       GROUP BY InvoiceNumber
     )
    
    UPDATE CTE_DocTotal
    SET DocTotal = CTE_DocTotal.DocTotal_1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-29
      • 2017-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多