带有 WHERE EXISTS 的 SQL UPDATE 语句
Posted
技术标签:
【中文标题】带有 WHERE EXISTS 的 SQL UPDATE 语句【英文标题】:SQL UPDATE statement with WHERE EXISTS 【发布时间】:2012-01-26 19:15:52 【问题描述】:我正在尝试编写一个查询,仅当我正在更新的组的 LINE_CD 为 50 时才更新日期。我会这样做吗?
UPDATE EMPLOYER_ADDL
SET EMPLOYER_ADDL.GTL_UW_APPRV_DT = EMPLOYER_ADDL.DNTL_UW_APPRV_DT
WHERE EXISTS
(
SELECT EMP_PLAN_LINE_INFO.LINE_CD
FROM EMP_PLAN_LINE_INFO
Where EMP_PLAN_LINE_INFO.GR_NBR = EMPLOYER_ADDL.GR_NBR and
EMP_PLAN_LINE_INFO.LINE_CD = 50
)
【问题讨论】:
你有很多“正确答案”,祝你好运。 【参考方案1】:UPDATE ea
SET GTL_UW_APPRV_DT = DNTL_UW_APPRV_DT
FROM EMPLOYER_ADDL AS ea
WHERE EXISTS
(
SELECT 1
FROM EMP_PLAN_LINE_INFO AS ep
WHERE ep.GR_NBR = ea.GR_NBR
AND ep.LINE_CD = 50
);
但是,如果您可以从查询中获取此信息,为什么还要更新表?似乎这必须不断运行,否则可能会过时。
【讨论】:
您应该明确提及列名。如果将来更改架构怎么办?所以应该是列名而不是 1... @***User - 这个实例没关系。他正在使用1
,因为EXISTS
短路,我们实际上并没有返回该字段。我们只想知道,一行是否满足列出的条件?
在 EXISTS 内部,列名无关紧要。您可以说 *、NULL、'constant' 等。 1 不是列名。如果架构发生变化并且您在其中提到了一个明确的列名,那不是 less 不会过时吗?
@*** 用户,我给出了在我投反对票时我反对你的答案的原因。您缺少“FROM”,并且不需要“SET”中的别名或表名。请不要在其他人的回答中询问有关您的回答的问题。
@BillOrtell 该语法适用于 Oracle,但不适用于 SQL Server。【参考方案2】:
这个怎么样?
UPDATE ea
SET ea.GTL_UW_APPRV_DT = ea.DNTL_UW_APPRV_DT
FROM EMPLOYER_ADDL ea
INNER JOIN EMP_PLAN_LINE_INFO ei ON(ei.GR_NBR = ea.GR_NBR)
WHERE
ei.LINE_CD = 50
【讨论】:
唯一的问题是,如果连接产生重复项(例如,如果 GR_NBR 在 EMPLOYER_ADDL 或 EMP_PLAN_LINE_INFO 中不是唯一的),则需要额外的工作。我认为 EXISTS 格式更安全,因为它可以满足这两种情况。 YMMV。 GR_NBR 在 EPLI 表中不是唯一的,但它在 ADDL 中。通过额外的工作,您是否意味着查询需要更长的时间才能运行?【参考方案3】:我相信这会给你同样的结果。
UPDATE ea
SET GTL_UW_APPRV_DT = DNTL_UW_APPRV_DT
FROM EMPLOYER_ADDL AS ea
INNER JOIN EMP_PLAN_LINE_INFO AS ep
ON ep.GR_NBR = ea.GR_NBR
AND ep.LINE_CD = 50
【讨论】:
请拒绝投票的原因,以便我了解我做错了什么。 我没有投反对票,但我认为无论是谁投的票,可能是因为你的原始格式不好?我们在同一时间发布了几乎相同的内容,所以我不知道您为什么投了反对票。 我从记事本复制了它。当我添加答案时,它搞砸了格式。无论如何继续前进.. 欢呼伙计们。【参考方案4】:假设 GR_NBR 是一个 PK 并且在 EMP_Plan_line_Info 中是不同的:
UPDATE EA
SET GTL_UW_APPRV_DT = DNTL_UW_APPRV_DT
FROM EMPLOYER_ADDL EA
INNER JOIN EMP_PLAN_LINE_INFO EP
ON EP.GR_NBR = EA.GR_NBR
AND EP.LINE_CD = 50
【讨论】:
【参考方案5】:也试试这个。我认为这对你来说是新的?
UPDATE ADDL
SET ADDL.GTL_UW_APPRV_DT = ADDL.DNTL_UW_APPRV_DT
From EMPLOYER_ADDL ADDL
Inner Join EMP_PLAN_LINE_INFO INFO on INFO.GR_NBR = ADDL.GR_NBR
Where INFO.LINE_CD = 50
【讨论】:
No FROM,并且您不需要 ADDL。在 SET ADDL.GTL_UW_APPRV_DT = @DanAndrews 个人而言,我更喜欢明确。将别名放在SET
行有什么危害?这对于阅读您的代码但不知道别名并非绝对必要的同事很有帮助。如果您使用合理的别名,它应该有助于更好地记录代码,而不是使其阅读和理解更加麻烦。
@Aaron Bertrand,您正在设置您要更新的内容,没有什么可弄清楚的。投反对票的主要原因是缺少 FROM,现在已将其修改为包含。
@AaronBertrand 我看不到在 SET 行上有别名有任何价值。它不像它可以更新任何其他表。
这是主观的。你看不到任何价值,我看不到任何伤害。对于不了解 SQL Server 专有的 UPDATE FROM 语法的初级人员来说,使用别名更好地记录它是没有争议的。想象一个连接到 15 个表的更新,并且集合的右侧来自不同的表。我发现明确的价值。如果你不这样做,好的。【参考方案6】:
我相信存在需要通配符:
UPDATE EMPLOYER_ADDL
SET EMPLOYER_ADDL.GTL_UW_APPRV_DT = EMPLOYER_ADDL.DNTL_UW_APPRV_DT
WHERE EXISTS
(
SELECT *
FROM EMP_PLAN_LINE_INFO
Where EMP_PLAN_LINE_INFO.GR_NBR = EMPLOYER_ADDL.GR_NBR and
EMP_PLAN_LINE_INFO.LINE_CD = 50
)
不过,我更喜欢使用 IN。有人认为它可能会更慢,但我发现 2005 年及更高版本的 SQL 优化器使 IN 的工作方式与 EXISTS 相同,如果该字段是非空字段。
UPDATE EMPLOYER_ADDL
SET EMPLOYER_ADDL.GTL_UW_APPRV_DT = EMPLOYER_ADDL.DNTL_UW_APPRV_DT
WHERE EMPLOYER_ADDL.GR_NBR IN
(
SELECT EMP_PLAN_LINE_INFO.GR_NBR
FROM EMP_PLAN_LINE_INFO
Where EMP_PLAN_LINE_INFO.LINE_CD = 50
)
【讨论】:
不,EXISTS
不需要通配符。优化器完全忽略列列表。
点了。我见过的所有存在的例子都有一个通配符,但我从来没有彻底测试过它。我注意到你的回答只是做了一个选择 1.. 有趣。
WHERE 通配符是 %,SELECT 通配符是 *。引用所有字段。以上是关于带有 WHERE EXISTS 的 SQL UPDATE 语句的主要内容,如果未能解决你的问题,请参考以下文章
Oracle where exists 子句不适用于 SQL Plus
带有 Exists 的 WHERE CASE WHEN THEN 语句