来自数据库系统概念
假设我们有一个关系funds_received(dept_name,金额) 存储每个接收的资金(例如,通过电子资金转帐) 一组部门。现在假设我们要将金额加到 相应部门预算的余额。为了使用 要执行此任务的SQL更新语句,我们必须执行 查找每个元组中的已收资金关系 部门关系。我们可以在update子句中使用子查询来 请执行以下任务:为简单起见,我们假设 每个收到的关系基金最多包含一个元组 部门。
update department set budget = budget + (select amount from funds_received where funds_received.dept_name = department.dept_name) where exists( select * from funds_received where funds_received.dept_name = department.dept_name);
请注意,更新的where子句中的条件可确保 仅更新收到的资金中具有相应元组的帐户, 而set子句中的子查询计算的金额为 添加到每个这样的部门。
我想知道为什么我们需要where
子句来首先检查部门是否收到任何资金?
这两个子查询基本相同,并且看起来很多余。
没有where
子句的以下内容不能相同吗?
update department set budget = budget +
(select amount
from funds_received
where funds_received.dept_name = department.dept_name)
如果一个部门没有任何收到的资金,那么amount
将为空,而budge + ...
将不起作用?
我对SQL标准或PostgreSQL中的解决方案感兴趣。
谢谢。
答案 0 :(得分:2)
如果没有匹配项,则需要where
子句。如果是这样,则set
条件(按书面规定)将返回NULL
-可能是一件坏事。
但是Postgres使用from
有更好的解决方案:
update department d
set budget = d.budget + fr.amount
from funds_received fr
where fr.dept_name = d.dept_name;
答案 1 :(得分:1)
例如,如果处理WHERE
,则可能会留下外部NULL
子句。与coalesce()
。
UPDATE department
SET budget = budget
+
coalesce((SELECT amount
FROM funds_received
WHERE funds_received.dept_name = department.dept_name), 0);
这可以确保,如果一个部门没有收到任何资金,则不会返回NULL
,这也可能使附加收益NULL
(这可能取决于DBMS,在这种情况下会发生什么)一件事)。 coalesce()
会将NULL
变成0
,这是添加的中性元素,因此预算保持不变。
(假设funds_received.amount
永远不会是NULL
。如果它是NULL
,则coalesce()
无法“知道”,如果NULL
在那儿是因为没有找到记录,或者因为amount
实际上是NULL
。如果amount
实际上是NULL
,则原始查询会将NULL
添加到预算中,我的查询将添加一个0
。因此在这种情况下,查询是不等效的,但是我认为这本书的作者很有可能对NOT NULL
施加了这样一个隐含的funds_received.amount
约束记住。)
但是,另一方面,WHERE
子句可能会减少必须更新的行(即使更新实际上并没有改变值,也需要对行进行读写)和因此可以提高性能。