我正在尝试为可以拥有空JSON对象{}
的列设置唯一约束。我正在使用Postgres 9.6.3。
问题在于Postgres将它们视为唯一,因为我可以插入具有相同值的多个行。我认为这与Postgres如何将空值视为唯一有关。我怎么能绕过这个?
答案 0 :(得分:3)
使用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"
答案 1 :(得分:1)
您可以使用将json视为文本的常规唯一索引。这是一个完整的示例,显示它是如何工作的(更正):
创建表格:
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
如果此处的某些内容无法按预期运行,请澄清。
答案 2 :(得分:1)
当json表达式为空时,您需要另一个名称的部分索引
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