这可能在Oracle/Sql中吗?

Sha*_*ane 1 sql oracle triggers constraints

我有两张桌子:

CREATE TABLE Event_details( event_no INTEGER AUTOINCREMENT NOT NULL,
no_players INTEGER NOT NULL,
game_type VARCHAR(20) NOT NULL,
payout_positions INTEGER NOT NULL, 
PRIMARY KEY(event_no)
CONSTRAINT check_game_type CHECK(game_type IN ('NLH','NLO','PLO','PLH','STUD','HORSE')
CONSTRAINT check_no_players CHECK (no_players > 1)
CONSTRAINT check_payouts CHECK (payout_positions > 0 AND payout_positions < no_players));

CREATE TABLE Venue( venue_no INTEGER AUTOINCREMENT NOT NULL,
name VARCHAR(20) NOT NULL,
location VARCHAR(20) NOT NULL,
capacity INTEGER NOT NULL,
PRIMARY KEY (venue_no)
CONSTRAINT check_capacity CHECK (capacity > 0));
Run Code Online (Sandbox Code Playgroud)

和他们之间的外键:

ALTER TABLE Event_details
ADD FOREIGN KEY (venue_no)
REFERENCES Venue(venue_no)
ON DELETE SET NULL;
Run Code Online (Sandbox Code Playgroud)

我想设置一个CONSTRAINT(或TRIGGER ???),它不允许(或标记)一个条目,其中Event_details(no_players)<Venue(capacity),其中Venue(容量)是在外键行中找到的值.

这可能吗?

Jus*_*ave 6

关于您发布的DDL的几点评论.

  • AUTOINCREMENTOracle中没有关键字.您需要创建一个序列(通常每个表一个序列),并NEXTVALINSERT语句本身或触发器中使用序列来填充合成主键.
  • 没有任何东西可以创建一个VENUE_NOEVENT_DETAILS.我假设您的实际DDL正在定义该列.

您无法通过简单CHECK约束强制执行此操作.您可以创建一个触发器

CREATE OR REPLACE TRIGGER validate_capacity
  BEFORE INSERT OR UPDATE ON event_details
  FOR EACH ROW
DECLARE
  l_venue_capacity venue.capacity%type;
BEGIN
  SELECT capacity
    INTO l_venue_capacity
    FROM venue
   WHERE venue_no = :new.venue_no;

  IF( l_venue_capacity < :new.no_players )
  THEN
    RAISE_APPLICATION_ERROR( -20001, 'Sorry, the venue has insufficient capacity' );
  END IF;
END;
Run Code Online (Sandbox Code Playgroud)

但请注意

  • 您还需要在VENUE表格上设置一个触发器,以检查场地容量的变化是否会导致某些事件无效.通常,这需要在事件详细信息表中存在某种日期,因为可能地,场地的容量可能随时间而变化,并且您实际上只希望验证检查该场所中的未来事件.
  • 基于触发器的解决方案并不总是适用于多用户环境.想象一下,场地1的容量为30.现在,会话A将该容量更新为15.但是在会话A提交之前,会话B插入一个NO_PLAYERS20 的事件.会话的触发器都不会出现问题,因此两个更改都将被允许.但是,一旦两个会议都提交,将会有一个活动,在一个仅支持15名玩家的场地中预定20名玩家.触发器EVENT_DETAILS可能会锁定VENUE表中的行以避免此竞争条件,但是它们会在EVENT_DETAILS表上序列化插入和更新,这可能是性能问题,尤其是在应用程序在提交事务之前等待人工输入时.

作为触发器的替代方法,您可以创建一个ON COMMIT物化视图,将两个表连接在一起,并CHECK对该物化视图施加约束,强制要求玩家数量不能超过场地容量.这将在多用户环境中工作,但它需要两个基表上的物化视图日志,并将检查移动到会话提交的点,这可能有点棘手.大多数应用程序不考虑COMMIT语句可能失败的可能性,因此处理这些异常可能很棘手.从用户界面的角度来看,向用户解释问题是什么有点棘手,因为异常可能与事务中更早发生的更改有关.