问题描述
生成邮件的模式:<Firstname>.<Lastname>@test.org
示例表“人员”:
Firstname Lastname email
Henley figueroa none@none.com
Samina Morrison none@none.com
Dev Rowe none@none.com
表“人”的期望结果:
Firstname Lastname email
Henley figueroa Henley.figueroa@test.org
Samina Morrison Samina.Morrison@test.org
Dev Rowe Dev.Rowe@test.org
UPDATE Persons
SET
email = (SELECT FirstName || "." || LastName ||"@"||"test.org" FROM Persons)
表“人”的实际结果:
Firstname Lastname email
Henley figueroa Henley.figueroa@test.org
Samina Morrison Henley.figueroa@test.org
Dev Rowe Henley.figueroa@test.org
只重复使用返回结果表的第一条记录。为什么?
如果我省略 SELECT:
UPDATE Persons
SET
email = FirstName || "." || LastName ||"@"||"test.org"
我得到了预期的结果。
参考你的回答,我用两个表的例子来扩展我的问题。一个只有名字,第二个是邮件地址。
表人:
ID* | 名字 | 姓氏 |
---|---|---|
1 | 亨利 | 菲格罗亚 |
2 | 萨米娜 | 莫里森 |
3 | 开发 | 罗 |
表地址:
ID* | 电子邮件 |
---|---|
1 | wrong@wrong.ng |
2 | wrong@wrong,ng |
3 | wrong@wro.ng |
UPDATE Addresses
SET email = (SELECT Firstname ||"."|| Lastname || "@test.org"
FROM Persons WHERE Persons.id = Addresses.id)
这里使用 SET 和 SELECT 进行 UPDATE 工作(每个人都有一个唯一的邮件地址)。我不应该在这里遇到同样的问题吗? 从 SELECT 的输出中,我看到我再次(如预期的那样)获得了三个记录。
解决方法
您的问题有正确的语法。所以问题是为什么这不符合您的要求?
UPDATE Persons
SET email = (SELECT FirstName || "." || LastName ||"@"||"test.org"
FROM Persons
);
事实上,这应该会在任何 SQL 引擎中产生错误——尽管 SQLite 对此类错误可能有点松懈。为什么? SET
需要一个 single 值。这段代码有一个返回三个值的子查询。
注意:SQL Fiddle 确实表明 SQLite 接受此语法。啊!您可以将其切换到 Postgres 以查看错误。通过一些修改,对于使用 SQL Server 或 Oracle 或几乎任何数据库的创建代码,您还可以看到相同的错误(子查询返回多行)。
显然,SQLite 只是任意选择这些值之一——它第一次遇到的值。这对于所有三行都是相同的值。
您已经知道这里的子查询不正确。您的问题中有正确的代码。
,括号中的 SELECT 语句是子查询。所有类型的 SELECT 语句,包括聚合和复合 SELECT 查询 (带有 UNION 或 EXCEPT 等关键字的查询)被允许作为标量 子查询。 子查询表达式的值是第一行 包含的 SELECT 语句的结果。一个的价值 如果包含的 SELECT 语句返回,则子查询表达式为 NULL 没有行。
所以子查询得到的值是返回行的第一行。
当然,您不需要 SELECT
语句。
这是一个简单的 UPDATE
语句,只涉及当前行列的值:
UPDATE Persons
SET email = FirstName || '.' || LastName || '@' || 'test.org'
参见demo。
结果:
名字 | 姓氏 | 电子邮件 |
---|---|---|
亨利 | 菲格罗亚 | Henley.Figueroa@test.org |
萨米娜 | 莫里森 | Samina.Morrison@test.org |
开发 | 罗 | Dev.Rowe@test.org |
对于具有 2 个表的第二个查询:
我不应该在这里遇到同样的问题吗?
否,因为子查询是一个correlated子查询,它为表Addresses
中的每一行只返回1行(假设Persons
中没有重复的id),行匹配条件 Persons.id = Addresses.id
.
如果没有符合条件的行,则返回 NULL
。