Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle Sql检查约束_Sql_Oracle - Fatal编程技术网

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更新为更晚的日期
  • 删除事件
对于这些操作中的每一个,您都必须考虑通过在另一个表中锁定正确的记录来编写具有多用户证明的代码

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

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

希望这有帮助

问候,

罗伯。

你想做的事情远不是简单的

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

  • 插入游戏
  • 将gamedate更新为较短的日期
  • 将事件startdate更新为更晚的日期
  • 删除事件
对于这些操作中的每一个,您都必须考虑通过在另一个表中锁定正确的记录来编写具有多用户证明的代码

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

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

希望这有帮助

问候,

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