I have a table t, with a column called json, of type JSON. Within the JSON there is a natural key:
> SELECT json->'id' AS id FROM t LIMIT 1;
id
-----------------------------
" 63631ff3809de7a17398602f"
I can create a UNIQUE INDEX on id, thus:
> CREATE UNIQUE INDEX t_id ON t((json->>'id'));
CREATE INDEX
I'd like to add this as a table_constraint_using_index, but it fails for both PRIMARY KEY:
> ALTER TABLE t ADD CONSTRAINT t_pkey PRIMARY KEY USING INDEX t_id;
ERROR: index "t_id" contains expressions
LINE 1: ALTER TABLE t ADD CONSTRAINT t_pkey
^
DETAIL: Cannot create a primary key or unique constraint using such an index.
and UNIQUE:
> ALTER TABLE t ADD CONSTRAINT t_unique_id UNIQUE USING INDEX t_id;
ERROR: index "t_id" contains expressions
LINE 1: ALTER TABLE t ADD CONSTRAINT t_unique_id...
^
DETAIL: Cannot create a primary key or unique constraint using such an index.
Should I be able to add such a constraint?
ADD CONSTRAINT t_unique_id UNIQUEas shown in my second example? – davetapley May 01 '14 at 14:43UNIQUEconstraint cannot be partial or contain expressions. The issue is that SQL specifies what aPRIMARY KEYorUNIQUEconstraint is - PostgreSQL can't just redefine what they mean because they're part of the standard. It can and does provide extensions, but if it redefined the standard constraint types then apps that depended on their meanings might break. As for docs: No specific reference; Pg only recently added the ability to create a constraint using an existing index in the first place. Should add something to the docs... – Craig Ringer May 01 '14 at 15:31uniqueon an index was just a hint to the DB that the values were unique, but if you wanted uniqueness enforced you needed an explicitconstraint. As I now understand it, they're just two sides of the same coin, per this question :) – davetapley May 02 '14 at 00:35