(PostgreSQL)“高级”检查约束问题

时间:2011-03-06 09:49:31

标签: database postgresql foreign-keys constraints database-schema

我使用PostgreSQL但我正在寻找尽可能标准的SQL答案。

我有下表“docs” -

    Column  |          Type          | Modifiers              
------------+------------------------+--------------------
 id         | character varying(32)  | not null
 version    | integer                | not null default 1
 link_id    | character varying(32)  | 
 content    | character varying(128) | 
Indexes:
    "docs_pkey" PRIMARY KEY, btree (id, version)

id和link_id用于彼此之间具有链接关系的文档,因此link_id self引用id。

问题来自版本。现在id不再是主键(也不是唯一的),并且link_id不能将其作为外键引用 -

my_db=# ALTER TABLE docs ADD FOREIGN KEY(link_id) REFERENCES docs (id) ; 
ERROR:  there is no unique constraint matching given keys for referenced table "docs"

我试图在“if exists”之类的东西上搜索检查约束,但没有找到任何东西。

任何提示都会非常感激。

3 个答案:

答案 0 :(得分:4)

我通常喜欢这样:

table document (id, common, columns, current_revision)
table revision (id, doc_id, content, version)

表示该文档与其修订版本具有一对多关系,与当前版本一一对应。

这样,您始终可以通过简单的连接为当前修订选择一个完整的文档,并且您的文档表中只有一个唯一的行可以链接父/子关系,但仍然具有版本。< / p>

答案 1 :(得分:1)

尽可能靠近您的模型,您可以将表格拆分为两个,每个'doc'有一行,另一个''版本'有一行:

您有下表“版本” -

    Column  |          Type          | Modifiers              
------------+------------------------+--------------------
 id         | character varying(32)  | not null
 version    | integer                | not null default 1
 content    | character varying(128) | 
Indexes:
    "versions_pkey" PRIMARY KEY, btree (id, version)

以下表格“docs” -

    Column  |          Type          | Modifiers              
------------+------------------------+--------------------
 id         | character varying(32)  | not null
 link_id    | character varying(32)  | 
Indexes:
    "docs_pkey" PRIMARY KEY, btree (id)

现在

my_db=# ALTER TABLE docs ADD FOREIGN KEY(link_id) REFERENCES docs (id) ; 

是允许的,您还需要:

my_db=# ALTER TABLE versions ADD FOREIGN KEY(id) REFERENCES docs; 

当然,没有什么可以阻止你获得类似于原始表格的“组合”视图:

CREATE VIEW v_docs AS
SELECT id, version, link_id, content from docs join versions using(id);

答案 2 :(得分:0)

根据它是否是您想要的,您只需创建一个包含版本字段的FOREIGN KEY即可。这是指向一个独特行的唯一方法......

如果这不起作用,您可以编写TRIGGER(对于表上的所有UPDATE和INSERT)进行检查。请注意,您还需要在docs表上使用一个触发器,该触发器限制对该表的修改将破坏该键(例如键值本身的DELETE或UPDATE)。

您无法使用CHECK约束执行此操作,因为CHECK约束无法访问另一个表中的数据。