简体   繁体   中英

Oracle Sql Check Constraint

What I want to do is simple and below are details. I have two tables.

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

This is fine.

Here is second table.

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

The constraint checkDate is to check if the date is bigger than the startdate. While checking I'm getting error : Missing right parenthesis .

My question is, If this is possible to do then why it is giving me an error?

A check constraint in a table can only verify conditions on the columns of that particular table. You can not refer to columns from other tables.

If you need to verify conditions that involves columns from a different table, you can do it from a before insert/update trigger on that table.

What you want to do is far from simple.

The syntax you propose, doesn't work on any RDBMS. It would be nice to have, but none of the RDBMS vendors have implemented it, because it enforcing such a cross table integrity rule would mean locking the referenced table while updating the game table. If you try to build it yourself, you'll have to do the locking yourself. You'll have to take into account all actions that could possibly violate your rule, such as:

  • inserting a game
  • updating the gamedate to a less recent date
  • updating the event startdate to a more recent date
  • deleting an event

And for each of these actions you'll have to think of writing code that is multi user proof, by locking the right records in the other table.

If you want to reduce this complexity, you might want to look at a product called RuleGen (www.rulegen.com)

Or you may want to build a specific API and include the checks in just the right places. You'll still have to manually lock yourself in this scenario.

Hope this helps.

Regards,
Rob.

There is one hack that you can make, but I doubt that performance of inserting games or events will be acceptable, once the tables grow to a certain size:

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);

Now any transaction that inserts a game that starts before the referenced event will throw an error when trying to commit the transaction:

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

But again: This will make inserts in both tables slower as the query inside the mview needs to be run each time a commit is performed.

I wasn't able to change the refresh type to FAST which probably would improve commit performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM