Postgresql 当涉及“唯一索引”时,为什么更新查询结果会有差异?
我偶然遇到了一个问题,所以我试了一些东西 给定以下模式:Postgresql 当涉及“唯一索引”时,为什么更新查询结果会有差异?,postgresql,Postgresql,我偶然遇到了一个问题,所以我试了一些东西 给定以下模式: create table scientist (id integer PRIMARY KEY, firstname varchar(100), lastname varchar(100)); insert into scientist (id, firstname, lastname) values (1, 'albert', 'einstein'); insert into scientist (id,
create table scientist (id integer PRIMARY KEY, firstname varchar(100), lastname varchar(100));
insert into scientist (id, firstname, lastname) values (1, 'albert', 'einstein');
insert into scientist (id, firstname, lastname) values (2, 'isaac', 'newton');
insert into scientist (id, firstname, lastname) values (3, 'marie', 'curie');
select * from scientist;
CREATE UNIQUE INDEX fl_idx ON scientist(firstname, lastname);
运行此查询时:
UPDATE scientist AS c SET
firstname = new_values.F,
lastname = new_values.L
FROM (
SELECT * FROM
UNNEST(
ARRAY[1, 1]::numeric[],
ARRAY['one', 'v']::text[],
ARRAY['three', 'f']::text[]
) AS T(
I,
F,
L
)
) AS new_values
WHERE c.id = new_values.I
RETURNING c.id, c.firstname, c.lastname;
我回来了:
id firstname lastname
1 one three
然而,如果我不创建索引(create UNIQUE index fl_idx ON scientist(firstname,lastname);
),我会得到:
因此,我不确定为什么唯一索引
会影响结果,为什么当我将UNNEST
更改为(类似于我上面提到的So问题)时,id
是主键时,重复键值不会违反唯一约束
异常:
UNNEST(
ARRAY[1, 1]::numeric[],
ARRAY['one', 'one']::text[],
ARRAY['three', 'three']::text[]
)
我运行上述查询的postgres版本是:
x86_64-pc-linux-gnu上的PostgreSQL 11.11(Debian 11.11-0+deb10u1),由gcc(Debian 8.3.0-6)8.3.0编译,64位,来自:
使用FROM时,应确保联接为要修改的每一行最多生成一个输出行。换句话说,目标行不应连接到其他表中的多个行如果是,则只有一个联接行将用于更新目标行,但使用哪一个并不容易预测。
在本例中,1有两个匹配项,因此选择完全取决于读取的顺序行
以下是运行和结果都有索引的示例:
您知道为什么我没有得到“重复键值违反唯一约束”错误吗
执行更新后,列id上和对first\u name/last\u name上都没有重复的键
情景1:
+-----+------------+----------+
| id | firstname | lastname |
+-----+------------+----------+
| 2 | isaac | newton |
| 3 | marie | curie |
| 1 | v | f |
+-----+------------+----------+
情景2:
+-----+------------+----------+
| id | firstname | lastname |
+-----+------------+----------+
| 2 | isaac | newton |
| 3 | marie | curie |
| 1 | one | three |
+-----+------------+----------+
编辑:
使用“UPSERT”并尝试插入/更新行两次:
INSERT INTO scientist (id,firstname, lastname)
VALUES (1, 'one', 'three'), (1, 'v', 'f')
ON CONFLICT (id)
DO UPDATE SET firstname = excluded.firstname;
-- ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
发件人:
使用FROM时,应确保联接为要修改的每一行最多生成一个输出行。换句话说,目标行不应连接到其他表中的多个行如果是,则只有一个联接行将用于更新目标行,但使用哪一个并不容易预测。
在本例中,1有两个匹配项,因此选择完全取决于读取的顺序行
以下是运行和结果都有索引的示例:
您知道为什么我没有得到“重复键值违反唯一约束”错误吗
执行更新后,列id上和对first\u name/last\u name上都没有重复的键
情景1:
+-----+------------+----------+
| id | firstname | lastname |
+-----+------------+----------+
| 2 | isaac | newton |
| 3 | marie | curie |
| 1 | v | f |
+-----+------------+----------+
情景2:
+-----+------------+----------+
| id | firstname | lastname |
+-----+------------+----------+
| 2 | isaac | newton |
| 3 | marie | curie |
| 1 | one | three |
+-----+------------+----------+
编辑:
使用“UPSERT”并尝试插入/更新行两次:
INSERT INTO scientist (id,firstname, lastname)
VALUES (1, 'one', 'three'), (1, 'v', 'f')
ON CONFLICT (id)
DO UPDATE SET firstname = excluded.firstname;
-- ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
那很有趣,谢谢!你知道为什么我没有得到“重复键值违反唯一约束”错误吗?@Orestis没有重复项。相关:-这里不是PostgreSQL,但想法是一样的。当查询的unnest是:unnest(数组[1,1]::numeric[],数组['one','one']::text[],数组['three','three']::text[])时,我希望抛出因为我们尝试更新相同的id。我是否遗漏了什么?@Orestis仍然错误消息应该不同,因为没有重复。问题是您正在使用“波动”表作为源进行更新(可能有多个匹配)。这很有趣,谢谢!你知道为什么我没有得到“重复键值违反唯一约束”错误吗?@Orestis没有重复项。相关:-这里不是PostgreSQL,但想法是一样的。当查询的unnest是:unnest(数组[1,1]::numeric[],数组['one','one']::text[],数组['three','three']::text[])时,我希望抛出因为我们尝试更新相同的id。我是否遗漏了什么?@Orestis仍然错误消息应该不同,因为没有重复。问题是您正在使用“波动”表作为源进行更新(可能有多个匹配)。