我们可以减少更新语句中两个子查询之间的冗余吗?



>来自数据库系统概念

假设我们有一个关系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。如果是NULLcoalesce()就无法"知道",如果NULL在那里是因为没有找到记录,或者因为amount实际上是NULL。在amount实际NULL的情况下,原始查询将增加NULL预算,我的查询将添加0。因此,在这种情况下,查询并不等效。但我认为这本书的作者很可能对funds_received.amount有如此隐含的NOT NULL约束。

但另一方面,WHERE子句可能会减少必须更新的行(即使更新实际上不会更改值,也需要读取和写回行(,从而提高性能。

最新更新