下面的查询(来源于此处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、4和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时,应确保联接为要修改的每一行最多生成一个输出行。换句话说,目标行不应联接到其他表中的多个行。如果是这样,则只有一个联接行将用于更新目标行,但是将使用哪一个联接行并不容易预测。
由于这种不确定性,仅在子选择中引用其他表更安全,尽管通常比使用连接更难读取且速度更慢。
2条答案
按热度按时间cqoc49vn1#
您显示的
UPDATE
查询与以下内容完全相同:字符串
subject ILIKE '%tester%'
是subject ~ 'tester'
的更快等价物。有关LIKE
、ILIKE
和正则表达式匹配(~
)in the manual的详细信息,请参阅dba.SE上的相关答案:和 * 有效地 * 相同:
型
用这个代替。
如果表
email
中有多行具有相同的fromemailaddress
匹配fromemailaddress
中的一行,则此表单每行只执行***一次***更新,不像您不幸的原始表单。不要被这里使用
fromemailaddress
作为列和表名的事实所迷惑。仔细阅读手册here和here。特别是这一位:
表表达式的列表,允许其他表中的列出现在
WHERE
条件和更新表达式中。这类似于可以在SELECT
语句的FROM
子句中指定的表列表。请注意,目标表不能出现在***from_list***中,除非您打算进行自联接(在这种情况下,它必须以别名出现在***from_list***中)。m0rkklqb2#
这是一个内部连接。仅在
email.fromemailaddress = fromemailaddress.fromemailaddress
处更新记录。如果不是一对一的关系,那么email
中的一条记录将更新fromemailaddress
中的多条记录,或者email
中的许多记录将更新fromemailaddress
中的单个记录。前者就好了。我相信,如果你从源表中写入一个值,后者是不确定的。没有保证的结果,因为查询没有定义顺序。它将以查询引擎选择的任何顺序执行。举例来说:
字符串
现在,如果email/fromemailaddress关系是多对一的,那么您可能会遇到问题。
由于这个特定的查询总是将值设置为静态值,因此不存在确定性问题。