简体   繁体   English

SQL:在插入之前或更新之前有条件触发器

[英]SQL: Conditional Trigger BEFORE Insert or on Update

I have a table: 我有一张桌子:

Athlete : Athlete

Athlete_NO (PK) | Athlete_DOB |

and

Competes : Competes

Athlete_NO (PFK) | Discipline_Code |

and

Discipline : Discipline

Discipline_Code (PK) | Discipline_Name |

I'm trying to write a trigger which won't allow the insertion of an Athlete under the age of 18 for certain disciplines Ex. 我正在尝试编写一个触发器,该触发器不允许某些学科的Ex插入18岁以下的运动员。 Must be 18+ for Basketball 篮球必须年满18岁

I'm using Oracle SQL Developer 我正在使用Oracle SQL Developer

Any help is appreciated (-: 任何帮助表示赞赏(-:

The issue i'm facing is off incorporating "IF" under 18 for certain disciplines into the code. 我面临的问题是将某些学科的18岁以下的“ IF”纳入代码。

try this but its not tested yet 试试这个,但尚未测试

CREATE OR REPLACE TRIGGER athlete_insert BEFORE
  INSERT ON ATHLETE FOR EACH ROW DECLARE athlete_too_young EXCEPTION;
  BEGIN
    IF ((new.athelt_Birthday BETWEEN new.athelt_Birthday(YEAR,-19, GETDATE()) AND new.athelt_Birthday(DAY,-365,GETDATE())) / 365.242 < 16) THEN
      RAISE athlete_too_young;
    END IF;
  EXCEPTION
  WHEN athlete_too_young THEN
    RAISE_APPLICATION_ERROR(-20000, 'Athlete must be older than 16');
  END;

You will need triggers on both the involved tables for the integrity constraint, namely Athlete and Competes. 您需要在两个涉及的表上都需要触发器来进行完整性约束,即“运动员”和“比赛”。

In order to properly create this validation using a trigger a procedure should be created to obtain user-specified locks so the validation can be correctly serialized in a multi-user environment. 为了使用触发器正确地创建此验证,应该创建一个过程来获取用户指定的锁,以便可以在多用户环境中正确地序列化验证。

PROCEDURE request_lock
  (p_lockname                     IN     VARCHAR2
  ,p_lockmode                     IN     INTEGER  DEFAULT dbms_lock.x_mode
  ,p_timeout                      IN     INTEGER  DEFAULT 60
  ,p_release_on_commit            IN     BOOLEAN  DEFAULT TRUE
  ,p_expiration_secs              IN     INTEGER  DEFAULT 600)
IS
  -- dbms_lock.allocate_unique issues implicit commit, so place in its own
  -- transaction so it does not affect the caller
  PRAGMA AUTONOMOUS_TRANSACTION;
  l_lockhandle                   VARCHAR2(128);
  l_return                       NUMBER;
BEGIN
  dbms_lock.allocate_unique
    (lockname                       => p_lockname
    ,lockhandle                     => p_lockhandle
    ,expiration_secs                => p_expiration_secs);
  l_return := dbms_lock.request
    (lockhandle                     => l_lockhandle
    ,lockmode                       => p_lockmode
    ,timeout                        => p_timeout
    ,release_on_commit              => p_release_on_commit);
  IF    (l_return not in (0,4)) THEN
    raise_application_error(-20001, 'dbms_lock.request Failed ' || l_return);
  END IF;
  -- Must COMMIT an autonomous transaction
  COMMIT;
END request_lock;

This procedure can then be used in a trigger on each table eg 然后可以在每个表的触发器中使用此过程,例如

CREATE OR REPLACE TRIGGER competes_trg
AFTER INSERT OR UPDATE ON competes
FOR EACH ROW
DECLARE
  l_athlete_dob                  athlete.athlete_dob%TYPE; 
BEGIN
  request_lock('ATHLETE_AGE_' || :new.athlete_no);
  SELECT athelete_dob
  INTO l_athlete_dob
  FROM athlete
  WHERE athlete_no = :new.athlete_no;
  IF (  :new.discipline_code = 'BASKETBALL'
     AND (  l_athlete_dob IS NULL
         OR months_between(trunc(sysdate), l_athlete_dob)/12 < 18))
  THEN
    raise_application_error(-20000, 'Athlete must be 18 or over for Basketball');
  END IF;
END;

and

CREATE OR REPLACE TRIGGER athlete_trg
AFTER INSERT OR UPDATE ON athlete
FOR EACH ROW
DECLARE
  CURSOR csr_competes
  IS
  SELECT discipline_code
  FROM competes
  WHERE athlete_no = :new.athlete_no;
BEGIN
  request_lock('ATHLETE_AGE_' || :new.athlete_no);
  FOR r_compete IN csr_competes LOOP
    IF (  r_compete.discipline_code = 'BASKETBALL'
       AND (  :new.athlete_dob IS NULL
           OR months_between(trunc(sysdate), :new.athlete_dob)/12 < 18))
    THEN
      raise_application_error(-20000, 'Athlete must be 18 or over for Basketball');
    END IF;
  END IF;
END;

You can extend the IF condition to check for different ages for different disciplines. 您可以扩展IF条件,以检查不同学科的不同年龄。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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