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

Sql 我们可以减少update语句中两个子查询之间的冗余吗?,sql,postgresql,Sql,Postgresql,从数据库系统概念 假设我们收到了一个关系资金(部门名称、金额),它 存储每项业务收到的资金(例如,通过电子资金转账) 一组部门。假设现在我们要将金额添加到 相应部门预算的余额。为了使用 SQL update语句要执行此任务,我们必须执行 查找中每个元组的资金接收关系 部门关系。我们可以在update子句中使用子查询来 执行以下任务:为简单起见,我们假设 收到的关系资金最多包含一个元组 系 update department set budget = budget + (select amount

从数据库系统概念

假设我们收到了一个关系资金(部门名称、金额),它 存储每项业务收到的资金(例如,通过电子资金转账) 一组部门。假设现在我们要将金额添加到 相应部门预算的余额。为了使用 SQL update语句要执行此任务,我们必须执行 查找中每个元组的资金接收关系 部门关系。我们可以在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子句中的子查询则计算要查询的金额 增加到每个这样的部门

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
条款来首先检查一个部门是否收到任何资金

这两个子查询基本上是相同的,并且看起来是多余的

如果没有
where
子句,下列语句不能同样工作吗

 update department set budget = budget +
 (select amount
 from funds_received
 where funds_received.dept_name = department.dept_name)
如果一个部门没有收到任何资金,
金额
将为空,
预算+…
将不起作用

我对SQL标准或PostgreSQL中的解决方案感兴趣


谢谢。

您需要
where
子句,以防没有匹配项。如果是这样,那么
set
条件(如所写)将返回
NULL
——这可能是一件坏事

但是Postgres有一个更好的解决方案,使用来自的

update department d
    set budget = d.budget + fr.amount
from funds_received fr
where fr.dept_name = d.dept_name;

如果没有匹配项,则需要
where
子句。如果是这样,那么
set
条件(如所写)将返回
NULL
——这可能是一件坏事

但是Postgres有一个更好的解决方案,使用来自

update department d
    set budget = d.budget + fr.amount
from funds_received fr
where fr.dept_name = d.dept_name;

如果处理
NULL
s,例如使用
coalesce()
,则可以保留外部
WHERE
子句

这确保了,如果一个部门没有收到任何资金,则不会返回任何
NULL
,这可能会使添加产生
NULL
(这可能取决于DBMS,在这种情况下会发生什么情况)。
coalesce()
NULL
变为
0
,这是添加的中性元素,因此保持预算不变

(假设,
funds\u received.amount
不能为
NULL
。如果为
NULL
,则
coalesce()
不能“知道”,如果存在
NULL
是因为没有找到记录,或者因为
amount
实际上是
NULL
。如果
amount
实际上是
NULL
,原始查询将
NULL
添加到预算中,我的查询将添加一个
0
。因此,在这种情况下,查询并不等价。但是我我想这本书的作者很可能对所收到的资金有着这样一个隐含的限制


但另一方面,
WHERE
子句可能会减少必须更新的行(即使更新没有有效地更改值,也需要读取和写入行)因此有利于性能。

如果处理
NULL
s,例如使用
coalesce()
,则可以保留外部
WHERE
子句

这确保了,如果一个部门没有收到任何资金,则不会返回任何
NULL
,这可能会使添加产生
NULL
(这可能取决于DBMS,在这种情况下会发生什么情况)。
coalesce()
NULL
变为
0
,这是添加的中性元素,因此保持预算不变

(假设,
funds\u received.amount
不能为
NULL
。如果为
NULL
,则
coalesce()
不能“知道”,如果存在
NULL
是因为没有找到记录,或者因为
amount
实际上是
NULL
。如果
amount
实际上是
NULL
,原始查询将
NULL
添加到预算中,我的查询将添加一个
0
。因此,在这种情况下,查询并不等价。但是我我想这本书的作者很可能对所收到的资金有着这样一个隐含的限制


但另一方面,
WHERE
子句可能会减少必须更新的行(即使更新没有有效地更改值,也需要读取和写入行)因此有利于性能。

请注意:如果匹配行中的
amount
s曾经
NULL
,则这与此不同。这个数据不太可能是这样,但它值得理解。@GordonLinoff:正确的观点!谢谢我在答案中添加了这一点。请注意:如果匹配行中的
amount
s曾经
NULL
,则这与此不同。这个数据不太可能是这样,但它值得理解。@GordonLinoff:正确的观点!谢谢我在答案中加了这个。谢谢。(1) 如果
fr.amount
为空,使用
from
是否解决了问题?(2) 在
set
where
子句中,我们可以添加
d.
并任意删除它吗?例如,
budget
d.budget
可以任意交换吗?
dept\u name
d.dept\u name
可以任意交换吗?(3)来自
是否在
d
fr
之间创建一个叉积?@Ben。如果
fr.amount
NULL
,则任何简单添加的解决方案都将
budget
设置为
NULL
。您需要
coalesce()
。您应该限定查询t中的所有列名