Oracle Sql检查约束

时间:2012-01-22 03:20:17

标签: sql oracle

我想做的很简单,下面是细节。我有两张桌子。

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用于检查日期是否大于startdate。在检查我收到错误时:Missing right parenthesis

我的问题是,如果可以这样做那么为什么它会给我一个错误?

3 个答案:

答案 0 :(得分:4)

表中的检查约束只能验证该特定表的列上的条件。您不能引用其他表中的列。

如果需要验证涉及不同表中列的条件,可以从该表上的插入/更新触发器之前执行此操作。

答案 1 :(得分:0)

你想要做的远非简单。

您提出的语法不适用于任何RDBMS。它会很高兴,但没有一个RDBMS供应商实现它,因为它强制执行这样的交叉表完整性规则意味着在更新游戏表时锁定引用的表。如果您尝试自己构建它,则必须自己进行锁定。您必须考虑可能违反规则的所有操作,例如:

  • 插入游戏
  • 将比赛日期更新为不太新的日期
  • 将事件startdate更新为更新的日期
  • 删除活动

对于这些操作中的每一个,您都必须考虑编写多用户证明的代码,方法是将正确的记录锁定在另一个表中。

如果您想降低这种复杂性,您可能需要查看名为RuleGen的产品(www.rulegen.com)

或者您可能希望构建特定的API并将检查包含在正确的位置。在这种情况下,您仍然需要手动锁定自己。

希望这有帮助。

的问候,
罗布。

答案 2 :(得分:0)

你可以制作一个黑客,但我怀疑一旦桌子增长到一定的规模,插入游戏或事件的性能是可以接受的:

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,这可能会提高提交性能。