Как я могу применить ограничение, только если столбец не является нулевым в Postgresql? - PullRequest
8 голосов
/ 24 февраля 2009

Я бы хотел, чтобы решение обеспечивало ограничение, только если столбец не является нулевым. Я не могу найти способ сделать это в документации.

create table mytable(
  table_identifier_a INTEGER,
  table_identifier_b INTEGER,
  table_value1,...)

В зависимости от характера данных, у меня будет идентификатор b и значение при создании таблицы. После того, как мы получим дополнительные данные, я смогу заполнить идентификатор а. На данный момент я хотел бы обеспечить unique key of (identifier_a, value1), но только если существует identifier_a.

Надеюсь, это имеет смысл. У кого-нибудь есть идеи?

Ответы [ 5 ]

7 голосов
/ 24 февраля 2009

Мммм. Уникальные ограничения не предотвращают множественные значения NULL.

CREATE TABLE mytable (
    table_identifier_a   INTEGER    NULL,
    table_identifier_b   INTEGER    NOT NULL,
    table_value1         INTEGER    NOT NULL,

    UNIQUE(table_identifier_a, table_identifier_b)
);

Обратите внимание, что мы можем вставить в него несколько NULL, даже когда identifier_b матчи:

test=# INSERT INTO mytable values(NULL, 1, 2);
INSERT 0 1
test=# INSERT INTO mytable values(NULL, 1, 2);
INSERT 0 1
test=# select * from mytable;
 table_identifier_a | table_identifier_b | table_value1 
--------------------+--------------------+--------------
                    |                  1 |            2
                    |                  1 |            2
(2 rows)

Но мы не можем создать дубликаты (a, b) пар:

test=# update mytable set table_identifier_a = 3;
ERROR:  duplicate key value violates unique constraint "mytable_table_identifier_a_key"

Конечно, у вас есть проблема: у вашей таблицы нет первичного ключа. Вы вероятно, есть проблема с моделью данных. Но вы не предоставили достаточно детали, чтобы это исправить.

1 голос
/ 24 февраля 2009

На самом деле, я бы разбил это на две таблицы. Вы моделируете два разных типа вещей. Первая - это первоначальная версия, которая является только частичной, а вторая - целой. После того, как информация, необходимая для того, чтобы перенести первый тип вещей во вторую, переместит строку из одной таблицы в другую.

1 голос
/ 24 февраля 2009

Если выполнимо выполнить всю операцию в пределах одной транзакции, можно изменить время, в течение которого postgres оценивает ограничение, т.е.

START;
SET CONSTRAINTS <...> DEFERRED;
<SOME INSERT/UPDATE/DELETE>
COMMIT;

В этом случае ограничение оценивается при коммите. Увидеть: Postgres 7.4 Doc - Установить ограничения или Postgres 8.3 Doc

0 голосов
/ 24 февраля 2009

На вашем месте я бы разбил таблицу на две таблицы и, возможно, создал бы представление, которое объединит их при необходимости.

0 голосов
/ 24 февраля 2009

Вы можете справиться с этим, используя триггер вместо ограничения.

...