(PostgreSQL)“高级”检查约束问题
我使用 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自引用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"
我尝试搜索诸如“如果存在”之类的检查约束,但没有找到任何内容。
任何提示将不胜感激。
I use PostgreSQL but am looking for SQL answer as standard as possible.
I have the following table "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 and link_id are for documents that have linkage relationship between each other, so link_id self references id.
The problem comes with version. Now id is no longer the primary key (won't be unique either) and can't be referenced by by link_id as foreign key --
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"
I tried to search for check constraint on something like "if exists" but didn't find anything.
Any tip will be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我通常这样做:
这意味着该文档与其修订版具有一对多关系,并且与当前修订版具有一对一关系。
这样,您始终可以通过简单的联接为当前修订选择完整的文档,并且文档表中只有一个唯一的行,您可以在其中链接父/子关系,但仍然具有版本控制。
I usually do like this:
which means that document has a one-to-many relation with it's revisions, AND a one-to-one to the current revision.
That way, you can always select a complete document for the current revision with a simple join, and you will only have one unique row in your documents table which you can link parent/child relations in, but still have versioning.
尽可能贴近您的模型,您可以将表分成两部分,一个每个“文档”有 1 行,另一个每个“版本”有 1 行:
您有下表“版本”——
以及下表“docs”——
现在
是允许的,并且您也想要:
当然没有什么可以阻止您获得类似于原始表的“组合”视图:
Sticking as close to your model as possible, you can split your table into two, one which has 1 row per 'doc' and one with 1 row per 'version':
You have the following table "versions" --
And the following table "docs" --
now
is allowed, and you also want:
of course there is nothing stoping you getting a 'combined' view similar to your original table:
根据您是否需要,您可以简单地创建一个包含版本字段的外键。这是指向唯一行的唯一方法...
如果这不起作用,您可以编写一个触发器(针对表上的所有更新和插入)来进行检查。请注意,您还需要 docs 表上的触发器,以限制对该表进行会破坏键的修改(例如对键值本身的 DELETE 或 UPDATE)。
您不能使用 CHECK 约束来执行此操作,因为 CHECK 约束无法访问另一个表中的数据。
Depending on if it's what you want, you can simply create a FOREIGN KEY that includes the version field. That's the only way to point to a unique row...
If that doesn't work, you can write a TRIGGER (for all UPDATEs and INSERTs on the table) that makes the check. Note that you will also need a trigger on the docs table, that restricts modifications on that table that would break the key (such as a DELETE or UPDATE on the key value itself).
You cannot do this with a CHECK constraint, because a CHECK constraint cannot access data in another table.