微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

INSERT ON DUPLICATE 语句返回什么?

如何解决INSERT ON DUPLICATE 语句返回什么?

在 Postgresql 中,当插入带有 on conflictreturning 子句的行时,返回什么?插入的行?插入前的行?如果没有插入行怎么办?

考虑以下使用 ... on conflict do nothing returning ... 的语句:

insert into test
values (:id,:name)
on conflict do nothing
returning id;

以及以下语句 ... on conflict (...) do update ... returning ...

insert into test
values (:id,:name)
on conflict (name) do update
set id = EXCLUDED.id + 10
returning id;

并假设 idname 列都是唯一的。以上语句将返回什么?

密切相关,如何找到导致冲突的现有行的 ID?

PS:是的,我可以轻松地尝试一下。事实上,这就是我所做的(见答案)。很容易做出错误的猜测,很难记住答案,而且重现实验的成本很高,所以我认为这个问题对其他人有用。

解决方法

returning 子句总是返回写入到表中的信息(即插入或更新)。如果没有发生写入,则不会返回任何行。

因此,如果您想获取导致冲突的现有行的 id,则不能使用 on conflict do nothing。相反,您可以使用带有虚拟更新的 on conflict (...) do update 来引发实际上不修改现有行内容的写入,如下所示:

insert into test
values (4,'singleton')
on conflict (name) do update
set id = test.id -- force a write,but don't change anything
returning id;

但是请注意,这种人为写入可能仍然会产生不良副作用,尤其是在触发器到位的情况下。即使数据没有改变,您也会生成新的元组。

实验证明:

drop table if exists test;
create table test (
    id int primary key,name text unique
);

insert into test
values (1,'singleton');

select * from test;
-- +--+---------+
-- |id|name     |
-- +--+---------+
-- |1 |singleton|
-- +--+---------+

insert into test
values (2,'singleton')
on conflict do nothing
returning id;
-- result: empty

insert into test
values (2,'something else')
on conflict (name) do update
    set id = EXCLUDED.id + 10
returning id;
-- result:
-- +--+
-- |id|
-- +--+
-- |2 |
-- +--+

insert into test
values (3,'singleton')
on conflict (name) do update
set id = EXCLUDED.id + 10
returning id;
-- result:
-- +--+
-- |id|
-- +--+
-- |13|
-- +--+

insert into test
values (4,'singleton')
on conflict (name) do update
set id = test.id
returning id;
-- result:
-- +--+
-- |id|
-- +--+
-- |13|
-- +--+

select * from test;
-- result:
-- +--+--------------+
-- |id|name          |
-- +--+--------------+
-- |2 |something else|
-- |13|singleton     |
-- +--+--------------+

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。