Oracle Sql检查约束
我想做的很简单,下面是细节。我有两张桌子Oracle Sql检查约束,sql,oracle,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 &g
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。检查时出现错误:缺少右括号
我的问题是,如果这是可能的,那么为什么它会给我一个错误?表中的检查约束只能验证该特定表的列上的条件。不能引用其他表中的列
如果需要验证涉及不同表中列的条件,可以通过该表上的“插入前/更新”触发器进行验证。表中的检查约束只能验证该特定表中列的条件。不能引用其他表中的列
如果需要验证涉及不同表中的列的条件,可以从该表上的before insert/update触发器中执行此操作。您要做的远不简单 您提出的语法不适用于任何RDBMS。拥有它会很好,但没有一家RDBMS供应商实现了它,因为它强制执行这样的跨表完整性规则意味着在更新游戏表时锁定引用表。如果您试图自己构建它,您将不得不自己进行锁定。您必须考虑所有可能违反规则的行为,例如:
- 插入游戏
- 将gamedate更新为较短的日期
- 将事件startdate更新为更晚的日期
- 删除事件
罗伯。你想做的事情远不是简单的 您提出的语法不适用于任何RDBMS。拥有它会很好,但没有一家RDBMS供应商实现了它,因为它强制执行这样的跨表完整性规则意味着在更新游戏表时锁定引用表。如果您试图自己构建它,您将不得不自己进行锁定。您必须考虑所有可能违反规则的行为,例如:
- 插入游戏
- 将gamedate更新为较短的日期
- 将事件startdate更新为更晚的日期
- 删除事件
Rob。有一种方法是可以进行的,但我怀疑,一旦表格增长到一定的大小,插入游戏或事件的性能是否可以接受:
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
,这可能会提高提交性能。您可以进行一项黑客攻击,但我怀疑一旦表增长到一定大小,插入游戏或事件的性能是否可以接受:
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
,这可能会提高提交性能。因此,如果在Event
中有5条记录,您想与GameDate
进行比较吗,如果在事件
中有5条记录,您想将其与游戏日期
进行比较,则为True。这在性能方面是不可行的。在并发更新期间,您将遇到一些额外的争用()。请注意,将rowid添加到join mv时,可以快速刷新物化视图。不需要包含新值。@RobvanWijk:感谢您提供有关快速刷新的提示。我以为我在一次尝试中添加了rowids(但可能只是日志)是真的。这在性能方面是不可行的。在并发更新期间,您将遇到一些额外的争用()。请注意,将rowid添加到join mv时,可以快速刷新物化视图。不需要包含新值。@RobvanWijk:感谢您提供有关快速刷新的提示。我想我在我的一次尝试中添加了rowids(但可能只是日志)耶需要一个触发器:(谢谢你的解释Raihan耶需要一个触发器:(谢谢你的解释Raihan