>来自数据库系统概念
假设我们有一个关系funds_received(dept_name,金额( 存储funds_received(例如,通过电子资金转帐(每个 一组部门。假设现在我们要将金额添加到 相应部门预算的余额。为了使用 SQL 更新语句 要执行此任务,我们必须执行 查找每个元组中收到的资金关系 部门关系。我们可以在更新子句中使用子查询来 执行此任务,如下所示:为简单起见,我们假设 收到的关系资金最多包含一个元组 部门。
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的解决方案感兴趣。
谢谢。
您需要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;
如果您处理NULL
例如coalesce()
,则可以保留外部WHERE
子句。
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
。因此,在这种情况下,查询并不等效。但我认为这本书的作者很可能对funds_received.amount
有如此隐含的NOT NULL
约束。
但另一方面,WHERE
子句可能会减少必须更新的行(即使更新实际上不会更改值,也需要读取和写回行(,从而提高性能。