(PostgreSQL) "Расширенный" Проверка вопроса об ограничении - PullRequest
0 голосов
/ 06 марта 2011

Я использую 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"

Я пытался найти проверочное ограничение для чего-то вроде "если существует ", но ничего не нашел.

Любой совет будет высоко ценится.

Ответы [ 3 ]

4 голосов
/ 06 марта 2011

Обычно я делаю так:

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

, что означает, что документ имеет отношение один ко многим с его ревизиями, И один к одному с текущей ревизией.

Таким образом, вы всегда можете выбрать полный документ для текущей ревизии с простым соединением, и у вас будет только одна уникальная строка в таблице документов, с которой вы можете связать отношения родитель / потомок, но при этом иметь управление версиями.

1 голос
/ 07 марта 2011

Придерживаясь как можно ближе к вашей модели, вы можете разделить таблицу на две части: одну с 1 строкой на «документ» и одну с 1 строкой на «версию»:

У вас есть следующая таблица "версий" -

    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)

и следующая таблица "документы" -

    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);
0 голосов
/ 06 марта 2011

В зависимости от того, хотите ли вы, вы можете просто создать FOREIGN KEY, включающий поле версии.Это единственный способ указать на уникальную строку ...

Если это не сработает, вы можете написать TRIGGER (для всех UPDATE и INSERT в таблице), который выполняет проверку.Обратите внимание, что вам также потребуется триггер для таблицы документов, который ограничивает изменения в этой таблице, которые могут сломать ключ (например, DELETE или UPDATE для самого значения ключа).

Вы не можете сделать это с помощьюОграничение CHECK, поскольку ограничение CHECK не может получить доступ к данным в другой таблице.

...