具有空约束值的 Postgres UPSERT 行不起作用
Postgres UPSERT row with null constraint value not working
我正在尝试编写一个存储过程,即使键中的值之一为空,我也可以在其中插入一行。我已阅读文档,发现 Postgres 无法比较空值的相等性。
我还阅读了其他论坛帖子,发现我想要实现的目标可以通过部分索引来完成。我能够成功地违反约束,但是当我传入一个生日为空的值时,我的“冲突”永远不会被击中。
我希望能够传入一个空生日并更新一个人的 ID,即使他们的生日是空的。
(
id bigint not null,
name text,
birthday date
);
我创建了一个索引和部分索引,这样生日就可以为空
CREATE UNIQUE INDEX name_birthday_key on people (name, birthday);
CREATE UNIQUE INDEX birthday_null_key on people (name) where birthday is null;
create or replace procedure store_person(_identifier bigint, _name character varying, _birthday date)
language plpgsql
as
$$
begin
insert into people (
id, name, birthday
)
values (
_identifier, _name, _birthday
)
on conflict (name, birthday)
do update
set
id = _identifier
where people.birthday = _date and people.name = _name;
end
$$;
如果我运行:
call public.store_person(1, 'Bob', '1955-01-09')
call public.store_person(2, 'Bob', '1955-01-09')
我成功地看到数据库中唯一的行是 Bob,ID 为 2。
但是,如果我 运行
call public.store_person(3, 'Joe', null)
call public.store_person(4, 'Joe', null)
我得到的唯一行是 ID 3。ID 4 的第二个插入从不更新现有行。我确实收到违规错误,但“冲突”更新从未被击中。
有人可以指出正确的操作方向吗?
CONFLICT
不匹配,因为 NULL
不等于 NULL
。这不是 PostgreSQL 的东西,它是在 SQL 标准中定义的。
插入数据时使用类似 COALESCE(birthday, '0001-01-01')
的内容,这将匹配;并删除部分索引。
您的代码有一个错误,在 DO UPDATE...WHERE
中:没有名为 _date
的内容,应该是 _birthday
.
我正在尝试编写一个存储过程,即使键中的值之一为空,我也可以在其中插入一行。我已阅读文档,发现 Postgres 无法比较空值的相等性。
我还阅读了其他论坛帖子,发现我想要实现的目标可以通过部分索引来完成。我能够成功地违反约束,但是当我传入一个生日为空的值时,我的“冲突”永远不会被击中。
我希望能够传入一个空生日并更新一个人的 ID,即使他们的生日是空的。
(
id bigint not null,
name text,
birthday date
);
我创建了一个索引和部分索引,这样生日就可以为空
CREATE UNIQUE INDEX name_birthday_key on people (name, birthday);
CREATE UNIQUE INDEX birthday_null_key on people (name) where birthday is null;
create or replace procedure store_person(_identifier bigint, _name character varying, _birthday date)
language plpgsql
as
$$
begin
insert into people (
id, name, birthday
)
values (
_identifier, _name, _birthday
)
on conflict (name, birthday)
do update
set
id = _identifier
where people.birthday = _date and people.name = _name;
end
$$;
如果我运行:
call public.store_person(1, 'Bob', '1955-01-09')
call public.store_person(2, 'Bob', '1955-01-09')
我成功地看到数据库中唯一的行是 Bob,ID 为 2。 但是,如果我 运行
call public.store_person(3, 'Joe', null)
call public.store_person(4, 'Joe', null)
我得到的唯一行是 ID 3。ID 4 的第二个插入从不更新现有行。我确实收到违规错误,但“冲突”更新从未被击中。
有人可以指出正确的操作方向吗?
CONFLICT
不匹配,因为 NULL
不等于 NULL
。这不是 PostgreSQL 的东西,它是在 SQL 标准中定义的。
插入数据时使用类似 COALESCE(birthday, '0001-01-01')
的内容,这将匹配;并删除部分索引。
您的代码有一个错误,在 DO UPDATE...WHERE
中:没有名为 _date
的内容,应该是 _birthday
.