dav*_*ley 5 constraint postgresql-9.3 json
我有一个表t
,其中有一列名为json
,类型为JSON
。在 JSON 中有一个自然键:
> SELECT json->'id' AS id FROM t LIMIT 1;
id
-----------------------------
" 63631ff3809de7a17398602f"
Run Code Online (Sandbox Code Playgroud)
我可以创建一个UNIQUE INDEX
on id
,因此:
> CREATE UNIQUE INDEX t_id ON t((json->>'id'));
CREATE INDEX
Run Code Online (Sandbox Code Playgroud)
我想将其添加为table_constraint_using_index,但两者都失败了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.
Run Code Online (Sandbox Code Playgroud)
和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.
Run Code Online (Sandbox Code Playgroud)
我应该能够添加这样的约束吗?
正如克雷格的回答中所解释的,既PRIMARY KEY
不能UNIQUE
也不能使用。
但是,这里有一个两部分的解决方案来解决这个问题:
要强制执行not null,请使用检查约束,因此:
ALTER TABLE t ADD CONSTRAINT id_not_null CHECK ((json->>'id') IS NOT NULL);
Run Code Online (Sandbox Code Playgroud)要强制唯一性,请创建唯一索引*,因此:
CREATE UNIQUE INDEX t_id ON t ((json->>'id'))
Run Code Online (Sandbox Code Playgroud)在此之后,一个\d t
on inpsql
会给你:
Indexes:
"t_id" UNIQUE, btree ((json ->> 'id'::text))
Check constraints:
"id_not_null" CHECK ((json ->> 'id'::text) IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
你可以看到not null和uniqueness都被强制执行:
test=# INSERT INTO t VALUES ('{"no id" : "field here"}');
ERROR: new row for relation "t" violates check constraint "id_not_null"
DETAIL: Failing row contains ({"no id" : "field here"}).
test=# INSERT INTO t VALUES ('{"id" : "abc"}');
INSERT 0 1
test=# INSERT INTO t VALUES ('{"id" : "abc"}');
ERROR: duplicate key value violates unique constraint "t_id"
DETAIL: Key ((json ->> 'id'::text))=(abc) already exists
Run Code Online (Sandbox Code Playgroud)
* 请注意,仅存在t_id
索引就足以强制执行唯一性,即使它没有明确作为约束给出。
不,您不应该添加这样的约束。
的PRIMARY KEY
必须是简单或复合索引。它可能不是部分或表达式索引。
索引充当约束,在功能上它们大致相同,但它不能PRIMARY KEY
在表元数据中出现,也不能用作外键约束的目标。对于UNIQUE
约束也是如此。
这里的问题是,的SQL标准的定义PRIMARY KEY
和UNIQUE
约束不允许表达式或行匹配谓词。因此,如果 PostgreSQL 将表达式索引或部分索引列为约束,那么它就违反了标准,并向应用程序谎报了它在做什么。了解 PostgreSQL 特性的应用程序可以从 Pg 自己的目录中查找索引,并且 中也有信息information_schema
,但它不能作为列出的约束进入。
归档时间: |
|
查看次数: |
8952 次 |
最近记录: |