Oracle Sql Проверить ограничение - PullRequest
0 голосов
/ 22 января 2012

То, что я хочу сделать, просто, и ниже приведены подробности.У меня есть две таблицы.

Create Table Event(
IDEvent number (8) primary key,
StartDate date not null,
EndDate date not null
);

Это нормально.

Вот вторая таблица.

Create Table Game(
IDGame number (8) primary key,
GameDate date not null,
constraint checkDate 
check (GameDate >= to_date(StartDate references from Event(StartDate)))
);

Ограничение checkDate должно проверять, если дата больше чемНачальная дата.Во время проверки я получаю сообщение об ошибке: Missing right parenthesis.

Мой вопрос: если это возможно, то почему он выдает ошибку?

Ответы [ 3 ]

4 голосов
/ 22 января 2012

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

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

0 голосов
/ 22 января 2012

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

CREATE TABLE Event 
(
  IDEvent     NUMBER(8) PRIMARY KEY,
  StartDate   DATE NOT NULL,
  EndDate     DATE NOT NULL
);

CREATE TABLE Game 
(
  IDGame     NUMBER(8) PRIMARY KEY,
  GameDate   DATE NOT NULL,
  eventid    NUMBER(8),   -- this is different to your table definition
  CONSTRAINT fk_game_event FOREIGN KEY (eventid) REFERENCES event (idevent)
);

CREATE INDEX game_eventid ON game (eventid);

CREATE MATERIALIZED VIEW LOG ON event 
   WITH ROWID, SEQUENCE (idevent, startdate) INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG ON game 
   WITH ROWID, SEQUENCE (idgame, eventid, gamedate) INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW mv_event_game
REFRESH FAST ON COMMIT WITH ROWID
AS
SELECT ev.idevent, 
       ev.startdate, 
       g.gamedate
FROM event ev, game g
WHERE g.eventid = ev.idevent;  

ALTER TABLE mv_event_game 
  ADD CONSTRAINT check_game_start check (gamedate >= startdate);

Теперь любая транзакция, которая вставляетигра, которая запускается до того, как упомянутое событие вызовет ошибку при попытке совершить транзакцию:

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning and OLAP options

SQL> INSERT INTO event
  2  (idevent, startdate, enddate)
  3  values
  4  (1, date '2012-01-22', date '2012-01-24');

1 row created.

SQL>
SQL> INSERT INTO game
  2  (idgame, eventid, gamedate)
  3  VALUES
  4  (1, 1, date '2012-01-01');

1 row created.

SQL> commit;
commit
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-02290: check constraint (FOOBAR.CHECK_GAME_START) violated

Но опять же: это сделает медленной вставкой в ​​обе таблицытак как запрос внутри mview должен выполняться каждый раз, когда выполняется коммит.

Мне не удалось изменить тип обновления на FAST, что, вероятно, улучшило бы производительность фиксации.

0 голосов
/ 22 января 2012

То, что вы хотите сделать, далеко не просто.

Синтаксис, который вы предлагаете, не работает ни на одной СУБД.Было бы неплохо иметь, но ни один из поставщиков RDBMS не реализовал это, потому что применение такого правила целостности кросс-таблицы означало бы блокировку ссылочной таблицы при обновлении игровой таблицы.Если вы попытаетесь построить его самостоятельно, вам придется сделать блокировку самостоятельно.Вам нужно будет принять во внимание все действия, которые могут нарушать ваше правило, например:

  • вставка игры
  • обновление даты игры до менее поздней даты
  • обновление начальной даты события до более поздней даты
  • удаление события

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

Если вы хотите уменьшить эту сложность, вы можете посмотреть на продукт под названием RuleGen (www.rulegen.com)

Или вы можетехочу создать конкретный API и включить проверки только в нужных местах.В этом сценарии вам все равно придется вручную заблокироваться.

Надеюсь, это поможет.

С уважением,
Роб.

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