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