以下查询(来自此处Postgres SQL SELECT and UPDATE behaving differently)
update fromemailaddress
set call = true
from email
where email.fromemailaddress = fromemailaddress.fromemailaddress and
LOWER(email.subject) ~ 'tester';
我读它的方式是:
Line 1: update fromemailaddress
- 我们告诉数据库我们正在更新fromemailaddress表
Line 2: set call = true
- 我们告诉数据库名为" call"将设置为true
Line 3: from email
Line 4: where email.fromemailaddress = fromemailaddress.fromemailaddress and
Line 5: LOWER(email.subject) ~ 'tester';
- 现在好了,事情变得模糊了。这里到底发生了什么?似乎数据库以某种方式在第3行和第5行中获取查询结果,但是它如何告诉它在fromemailaddress表中更新哪些行?什么是伪码?它是这样的:
for each row in (query from lines 3, 4, 5)
set call=true?
我无法看到SQL更新的FROM端如何与另一方相关。
更新:
按照下面@ Erwin的回答中的有价值的链接,我将获得这些信息,这些信息是我试图理解的核心信息:
http://www.postgresql.org/docs/current/interactive/sql-update.html
当存在FROM子句时,基本上发生的是 目标表连接到from_list中提到的表,和 连接的每个输出行代表一个更新操作 目标表。使用FROM时,应确保连接生成 每个要修改的行最多一个输出行。换句话说,一个 目标行不应该从另一行连接到多个行 表(一个或多个)。如果是,则只使用其中一个连接行 更新目标行,但不会轻易使用哪一行 可预测的。
由于这种不确定性,仅在其中引用其他表 子选择更安全,但通常更难阅读和慢 使用连接。
答案 0 :(得分:1)
您显示的UPDATE
查询与以下内容完全相同:
UPDATE fromemailaddress f
SET call = true
FROM (
SELECT fromemailaddress
FROM email
WHERE subject ILIKE '%tester%'
) e
WHERE e.fromemailaddress = f.fromemailaddress;
subject ILIKE '%tester%'
与subject ~ 'tester'
相比更快。 LIKE
,ILIKE
和正则表达式匹配(~
)in the manual的详细信息或dba.SE上的相关答案:
有效地 与:
相同UPDATE fromemailaddress f
SET call = true
WHERE EXISTS (
SELECT 1
FROM email e
WHERE e.fromemailaddress = f.fromemailaddress
AND e.subject ILIKE '%tester%'
);
改为使用它。
如果表email
中有多个行与fromemailaddress
中的行匹配相同fromemailaddress
,则此表单只执行 一个 每行更新,与您不幸的原始版本不同。
不要因为fromemailaddress
在这里被用作列和表名这一事实而感到困惑。
<强> from_list 强>
表表达式列表,允许其他表中的列 出现在
WHERE
条件和更新表达式中。这是 类似于FROM
Clause中可以指定的表格列表 一个SELECT
声明。请注意,目标表不得出现在 from_list ,除非您打算自行加入(在这种情况下必须 在 from_list 中显示别名。
答案 1 :(得分:1)
这是一个内部联接。记录仅在email.fromemailaddress = fromemailaddress.fromemailaddress
处更新。如果它不是一对一关系,则email
中的一条记录将更新fromemailaddress
中的多条记录,或email
中的多条记录将更新fromemailaddress
中的单个记录。
前者很好。如果您从源表中写入值,那么后者是非确定性的。由于查询没有定义订单,因此无法保证结果。它将以查询引擎选择的任何顺序完成。例如:
update fromemailaddress
set call = email.call
from email
where email.fromemailaddress = fromemailaddress.fromemailaddress and
LOWER(email.subject) ~ 'tester';
现在,如果电子邮件/ fromemailaddress关系是多对一的,那么您可能会遇到问题。
由于此特定查询始终将值设置为静态值,因此没有确定性问题。