【问题标题】:SQL Update Statement -- Why does this work?SQL 更新语句——为什么会这样?
【发布时间】:2018-09-06 04:29:01
【问题描述】:

我编写了一个有效的查询并完成了我想要的,但我不知道为什么逻辑是有效的。我无法分享确切的表格,因为这些信息很敏感,但我会在下面重新创建。

Table_A 有三列:

Employee_ID, 
Condition, 
B_Confirmed_Flag

Table_B 有两列:

Employee_ID, 
Condition

我的目标是编写一个更新语句,只要 Table_B 中存在 Employee_ID -> Condition 组合,就将 Table_A 中的 B_Confirmed_Flag 更新为 1。

更新声明:

 UPDATE TABLE_A
    SET B_Confirmed_Flag = 1
    FROM TABLE_A
    WHERE TABLE_A.Condition IN (SELECT TABLE_B.CONDITION
                                FROM TABLE_B
                                WHERE TABLE_B.EMPLOYEE_ID = TABLE_A.EMPLOYEE_ID)

此更新语句似乎有效,但我对逻辑感到困惑。我会认为使用此更新语句我会不必要地标记某些行,其中 Table_B 中的多个 Employee_ID 在 Condition 列中具有相同的值。但是,该查询对我有用。

谢谢!

【问题讨论】:

  • 什么是主键?
  • @paparazzo employee_ID 是两个表中的主键

标签: sql sql-server sql-update


【解决方案1】:

之所以有效,是因为更新是逐行处理的

这样应该更有效率

UPDATE TABLE_A
SET B_Confirmed_Flag = 1
FROM TABLE_A
WHERE exists ( SELECT 1 
                 FROM TABLE_B
                 WHERE TABLE_B.EMPLOYEE_ID = TABLE_A.EMPLOYEE_ID 
                   and TABLE_B.Condition   = TABLE_A.CONDITION 
             ) 
 and (B_Confirmed_Flag <> 1 or B_Confirmed_Flag is null) 

如果是pk那么

UPDATE TABLE_A
SET B_Confirmed_Flag = 1
FROM TABLE_A
JOIN TABLE_B
  ON TABLE_B.EMPLOYEE_ID = TABLE_A.EMPLOYEE_ID 
 and TABLE_B.Condition   = TABLE_A.CONDITION 
 and (B_Confirmed_Flag <> 1 or B_Confirmed_Flag is null) 

【讨论】:

  • 问题是“为什么会这样?”不是如何重写它。
  • 你知道我的代码为什么有效吗?从逻辑上看它不应该起作用,因为我没有明确说明“Where Table_A.Condition = Table_B.Condition”,但它确实有效
【解决方案2】:

要回答它的工作原理,请分解类似于以下的查询: 对于表 A 中的每条记录,子查询表 B 中员工 id 匹配的所有记录。然后,如果表 A 中的记录具有子查询中存在的条件,则会发生更新。有效地为您提供有关 employeeID 和 Condition 的加入条件。

正如其他人已经回答的那样,重写您的查询将更容易阅读并且可能会更好。

【讨论】:

  • 英文解释很好,通俗易懂。标记为正确!
【解决方案3】:

假设你有这样的虚拟数据:

CREATE TABLE #table_A (Employee_ID INT, 
Condition VARCHAR(1), 
B_Confirmed_Flag BIT
)

CREATE TABLE #table_B (Employee_ID INT, 
Condition VARCHAR(1)
)

INSERT INTO #table_A (Employee_ID, Condition, B_Confirmed_Flag)
VALUES 
(1, 'A', 0),
(2, 'A', 0),
(3, 'A', 0),
(4, 'B', 0),
(5, 'B', 0),
(6, 'B', 0),
(7, 'B', 0)

INSERT INTO #table_B (Employee_ID, Condition)
VALUES 
(1, 'A'),
(3, 'A'),
(5, 'B'),
(6, 'B')

如果您运行这两个查询并打开执行计划,您将看到不同之处。

select * 
FROM #TABLE_A
WHERE #TABLE_A.Condition IN (SELECT #TABLE_B.CONDITION
                            FROM #TABLE_B
                            WHERE #TABLE_B.EMPLOYEE_ID = #TABLE_A.EMPLOYEE_ID)
select * 
FROM #TABLE_A
WHERE #TABLE_A.Condition IN (SELECT #TABLE_A.CONDITION
                            FROM #TABLE_A
                            WHERE #TABLE_A.EMPLOYEE_ID IN (1,4))

第一个是你的,第二个是样品。听起来您希望您的查询像这里的第二个一样工作。如果查询的 IN 部分应该返回应该更新 table_A 中所有记录的值,为什么不呢?如果您检查执行计划并查看嵌套循环谓词,您可以看到您的查询正在查看条件以及员工 ID。这就是为什么更新只更新它在表 B 中找到的员工以及他们的状况。

【讨论】:

  • 明白了!谢谢!
猜你喜欢
  • 2015-05-15
  • 2012-08-15
  • 2019-09-02
  • 2022-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多