вставить несколько строк, чтобы удовлетворить ограничение - PullRequest
0 голосов
/ 01 марта 2010

У меня две таблицы: колода (id) и карта (колода, цвет, ценность)

Колода

имеет следующие ограничения:

  • CHECK (fifty_two_cards_deck(id))
  • PRIMARY KEY (id)

    CREATE FUNCTION fifty_two_cards_deck (целое число в колоде) ВОЗВРАЩАЕТ логическое значение ЯЗЫК sql СТАБИЛЬНАЯ СТРОКА AS $ $ SELECT COUNT (*) = 52 С карты ГДЕ колода = $ 1 $ $;

и карта имеет следующие ограничения:

  • FOREIGN KEY (deck) REFERENCES deck(id)
  • PRIMARY KEY (deck, color, value)

Как мне вставить новую колоду?

Я пробовал это:

begin transaction;
INSERT INTO "public"."deck" ("id") VALUES (nextval('deck_id_seq'::regclass));
INSERT INTO "public"."card" ("deck", "color", "value") VALUES ('1', enum_first(null::Suit), enum_first(null::Symbol));

end transaction

(я должен был отредактировать fifty_two_cards_deck, чтобы он был one_card_deck для целей тестирования) но я получил эту ошибку:

Ошибка SQL:

ОШИБКА: новый ряд для отношения "колода" нарушает ограничение проверки "Fifty_two_cards_deck"

В заявлении: начать транзакцию; INSERT INTO "public". "Deck" ("id") ЦЕННОСТИ (NEXTVAL ( 'deck_id_seq' :: regclass)); INSERT INTO "public". "Card" ("колода", "color", "value") VALUES ('1', enum_first (нуль :: Suit), enum_first (нуль :: Symbol));

конец транзакции

Как я могу решить эту проблему, не снимая ограничений?

РЕДАКТИРОВАТЬ: решение

спасибо Магнусу Хагандеру, у меня получилось так (после установки отложенного внешнего ключа):

begin transaction;

SET CONSTRAINTS ALL DEFERRED;

INSERT INTO "public"."deck-card" ("deck", "position", "color", "value") VALUES (1, 0, enum_first(null::suit), enum_first(null::Symbol));
INSERT INTO "public"."deck" ("id") VALUES (1);

end transaction

1 Ответ

1 голос
/ 01 марта 2010

Это может сработать, если вы сделаете FOREIGN KEY с помощью DEFERRABLE, а затем установите для него значение DEFERRED. Затем вы вставляете в «карточный» стол сначала , а затем в «колоду». Проверочные ограничения выполняются во время вставки (таким образом, задолго до того, как записи в «карточке» существуют) и не могут быть отложены до конца транзакции.

Но на самом деле это не поможет обойти тот факт, что ваше ограничение нарушено и должно быть удалено;) Это ограничение CHECK будет проверять только строки, входящие в "деку". Но как только строка будет вставлена ​​туда, вы все равно сможете добавлять или удалять строки из таблицы «card», и ограничение CHECK не будет жаловаться - до следующего раза, когда вы попытаетесь изменить «deck».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...