Возможно ли это в Oracle / Sql? - PullRequest
       13

Возможно ли это в Oracle / Sql?

1 голос
/ 07 декабря 2011

У меня есть две таблицы:

CREATE TABLE Event_details( event_no INTEGER AUTOINCREMENT NOT NULL,
no_players INTEGER NOT NULL,
game_type VARCHAR(20) NOT NULL,
payout_positions INTEGER NOT NULL, 
PRIMARY KEY(event_no)
CONSTRAINT check_game_type CHECK(game_type IN ('NLH','NLO','PLO','PLH','STUD','HORSE')
CONSTRAINT check_no_players CHECK (no_players > 1)
CONSTRAINT check_payouts CHECK (payout_positions > 0 AND payout_positions < no_players));

CREATE TABLE Venue( venue_no INTEGER AUTOINCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
location VARCHAR(20) NOT NULL,
capacity INTEGER NOT NULL,
PRIMARY KEY (venue_no)
CONSTRAINT check_capacity CHECK (capacity > 0));

И внешний ключ между ними:

ALTER TABLE Event_details
ADD FOREIGN KEY (venue_no)
REFERENCES Venue(venue_no)
ON DELETE SET NULL;

Я хочу установить CONSTRAINT (или TRIGGER ???), который не будетразрешить (или пометить) запись, где Event_details (no_players) <Место (емкость), где Место (емкость) - это значение, найденное в строке внешнего ключа. </p>

Возможно ли это?

1 Ответ

6 голосов
/ 07 декабря 2011

Несколько комментариев к DDL, который вы разместили.

  • В Oracle нет ключевого слова AUTOINCREMENT. Вам нужно создать последовательность (обычно по одной последовательности на таблицу) и использовать NEXTVAL из последовательности либо в самом операторе INSERT, либо в триггере для заполнения синтетического первичного ключа.
  • Нет ничего, что создает столбец VENUE_NO в EVENT_DETAILS. Я предполагаю, что ваш фактический DDL определяет этот столбец.

Вы не можете применить это с помощью простого ограничения CHECK. Вы можете создать триггер

CREATE OR REPLACE TRIGGER validate_capacity
  BEFORE INSERT OR UPDATE ON event_details
  FOR EACH ROW
DECLARE
  l_venue_capacity venue.capacity%type;
BEGIN
  SELECT capacity
    INTO l_venue_capacity
    FROM venue
   WHERE venue_no = :new.venue_no;

  IF( l_venue_capacity < :new.no_players )
  THEN
    RAISE_APPLICATION_ERROR( -20001, 'Sorry, the venue has insufficient capacity' );
  END IF;
END;

Знайте, однако, что

  • Вам также понадобится триггер в таблице VENUE, который проверяет, приводит ли изменение вместимости места проведения определенных событий к недействительности. Как правило, для этого требуется, чтобы в таблице сведений о событии была указана какая-то дата, поскольку, предположительно, емкость места может меняться со временем, и вы действительно хотите, чтобы валидация проверяла только будущие события в этом месте.
  • Решения на основе триггеров не всегда будут работать в многопользовательских средах. Представьте себе, что место 1 имеет емкость 30. Теперь сеанс A обновляет эту емкость до 15. Но перед тем, как сеанс A фиксируется, сеанс B вставляет событие с NO_PLAYERS из 20. Ни один из триггеров сеанса не увидит проблему, поэтому оба изменения будут позволил. Но как только обе сессии зафиксируются, в зале будет забронировано событие с 20 игроками, которое поддерживает только 15 игроков. Триггер на EVENT_DETAILS потенциально может заблокировать строку в таблице VENUE, чтобы избежать этого условия гонки, но они сериализуют вставки и обновления в таблицу EVENT_DETAILS, что может быть проблемой производительности, особенно если ваше приложение когда-либо ожидает человеческий вклад перед совершением транзакции.

В качестве альтернативы триггерам вы можете создать материализованное представление ON COMMIT, которое объединит две таблицы и наложит ограничение CHECK на это материализованное представление, которое предписывает требование, чтобы количество игроков не превышало вместимость места проведения. Это будет работать в многопользовательской среде, но для этого требуются материализованные журналы представлений в обеих базовых таблицах, и это перемещает проверку в точку, в которой сеансы фиксируются, что может быть немного сложнее. Большинство приложений не рассматривают возможность сбоя оператора COMMIT, поэтому обработка этих исключений может быть сложной. А с точки зрения пользовательского интерфейса может быть несколько сложно объяснить пользователю, в чем проблема, поскольку исключение может относиться к изменениям, сделанным намного раньше в транзакции.

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