如何使一个空的 JSON 对象在 Postgres 中不是唯一的?
How to make an empty JSON object not unique in Postgres?
我正在尝试对可以具有空 JSON 对象 {}
的列设置唯一约束。我正在使用 Postgres 9.6.3。
问题是 Postgres 将它们视为唯一的,因为我可以插入具有相同值的多行。我认为这与 Postgres 如何将 null 值视为唯一有关。我怎样才能避免这种情况?
您可以使用普通的唯一索引将 json 视为文本。这是一个显示其工作原理的完整示例(已更正):
创建 table:
create table tmp (payload json, name text);
创建我们的索引:
create unique index testindex on tmp ((payload::text), name);
插入一些行。前四个会起作用,其余的会失败。
insert into tmp (payload, name) values ('{}', 'foo');
// Succeeds
insert into tmp (payload, name) values ('{}', 'bar');
// Succeeds
insert into tmp (payload, name) values ('{"a":"b"}'::json, 'foo');
// Succeeds
insert into tmp (payload, name) values ('{"a":"b"}'::json, 'bar');
// Succeeds
insert into tmp (payload, name) values ('{"a":"b"}'::json, 'foo');
// Fails due to index
insert into tmp (payload, name) values ('{}', 'bar');
// Fails due to index
如果这里的某些地方没有按您预期的那样工作,请澄清。
使用 jsonb
类型,唯一约束按预期工作:
create table my_table(
id serial primary key,
jdata jsonb unique
);
insert into my_table (jdata)
values
('{}'),
('{}');
ERROR: duplicate key value violates unique constraint "my_table_jdata_key"
当 json 表达式为 null
时,您需要名称的另一个部分索引
CREATE TABLE action (
id BIGSERIAL PRIMARY KEY,
name text,
payload json
);
create unique INDEX actions_constraint on action (((payload#>>'{message, payload, content}')::text), name);
insert into action(name,payload) values ('a','{}');--works
insert into action(name,payload) values ('a','{}');--works
create unique INDEX actions_constraint_on_empty on action (name) where (payload::text = '{}');
--fails
truncate action;
create unique INDEX actions_constraint_on_empty on action (name) where (payload::text = '{}');
--works
insert into action(name,payload) values ('a','{}');
--works
insert into action(name,payload) values ('a','{}');
--fails
我正在尝试对可以具有空 JSON 对象 {}
的列设置唯一约束。我正在使用 Postgres 9.6.3。
问题是 Postgres 将它们视为唯一的,因为我可以插入具有相同值的多行。我认为这与 Postgres 如何将 null 值视为唯一有关。我怎样才能避免这种情况?
您可以使用普通的唯一索引将 json 视为文本。这是一个显示其工作原理的完整示例(已更正):
创建 table:
create table tmp (payload json, name text);
创建我们的索引:
create unique index testindex on tmp ((payload::text), name);
插入一些行。前四个会起作用,其余的会失败。
insert into tmp (payload, name) values ('{}', 'foo');
// Succeeds
insert into tmp (payload, name) values ('{}', 'bar');
// Succeeds
insert into tmp (payload, name) values ('{"a":"b"}'::json, 'foo');
// Succeeds
insert into tmp (payload, name) values ('{"a":"b"}'::json, 'bar');
// Succeeds
insert into tmp (payload, name) values ('{"a":"b"}'::json, 'foo');
// Fails due to index
insert into tmp (payload, name) values ('{}', 'bar');
// Fails due to index
如果这里的某些地方没有按您预期的那样工作,请澄清。
使用 jsonb
类型,唯一约束按预期工作:
create table my_table(
id serial primary key,
jdata jsonb unique
);
insert into my_table (jdata)
values
('{}'),
('{}');
ERROR: duplicate key value violates unique constraint "my_table_jdata_key"
当 json 表达式为 null
时,您需要名称的另一个部分索引CREATE TABLE action (
id BIGSERIAL PRIMARY KEY,
name text,
payload json
);
create unique INDEX actions_constraint on action (((payload#>>'{message, payload, content}')::text), name);
insert into action(name,payload) values ('a','{}');--works
insert into action(name,payload) values ('a','{}');--works
create unique INDEX actions_constraint_on_empty on action (name) where (payload::text = '{}');
--fails
truncate action;
create unique INDEX actions_constraint_on_empty on action (name) where (payload::text = '{}');
--works
insert into action(name,payload) values ('a','{}');
--works
insert into action(name,payload) values ('a','{}');
--fails