Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.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
SQL:插入前或更新时的条件触发器_Sql_Oracle - Fatal编程技术网

SQL:插入前或更新时的条件触发器

SQL:插入前或更新时的条件触发器,sql,oracle,Sql,Oracle,我有一张桌子: 运动员: Athlete_NO (PK) | Athlete_DOB | 及 比赛: Athlete_NO (PFK) | Discipline_Code | 及 专业: Discipline_Code (PK) | Discipline_Name | 我正在尝试写一个触发器,它不允许在某些学科中插入18岁以下的运动员,例如篮球必须是18岁以上 我正在使用Oracle SQL Developer 感谢您的帮助(-: 我面临的问题是在代码中加入18岁以下某些学科的“如果”。试

我有一张桌子:

运动员

Athlete_NO (PK) | Athlete_DOB |

比赛

Athlete_NO (PFK) | Discipline_Code |

专业

Discipline_Code (PK) | Discipline_Name |
我正在尝试写一个触发器,它不允许在某些学科中插入18岁以下的运动员,例如篮球必须是18岁以上

我正在使用Oracle SQL Developer

感谢您的帮助(-:


我面临的问题是在代码中加入18岁以下某些学科的“如果”。

试试这个,但它还没有经过测试

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;
在插入之前创建或替换触发器
每行插入运动员声明运动员太年轻例外;
开始
如果((new.athelt_生日介于new.athelt_生日(年份,-19,GETDATE())和new.athelt_生日(日期,-365,GETDATE())/365.242<16)之间),则
把运动员培养得太年轻;
如果结束;
例外情况
当你太年轻的时候
RAISE_应用程序_错误(-20000,‘运动员必须大于16岁’);
结束;

对于完整性约束,您需要在涉及的两个表上使用触发器,即运动员和竞赛

为了使用触发器正确创建此验证,应创建一个过程以获取用户指定的锁,以便在多用户环境中正确序列化验证

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;
然后可以在每个表上的触发器中使用此过程,例如

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;
创建或替换触发器
在比赛中插入或更新后
每行
声明
l_运动员_dob运动员。运动员_dob%类型;
开始
请求锁定(“运动员年龄”:新。运动员编号);
选择删除对象
成为l_运动员
来自运动员
其中,运动员编号=:new.attacher\u编号;
如果(:new.practice_代码='BASKETBALL'
和(l_)dob为空
或(trunc(系统日期)、l_运动员/U dob)/12<18)之间的月份
然后
提出申请错误(-20000,“运动员必须年满18岁才能参加篮球比赛”);
如果结束;
结束;

创建或替换触发器\u trg
在运动员上插入或更新后
每行
声明
你参加比赛了吗
是
选择专业代码
来自竞争
其中,运动员编号=:new.attacher\u编号;
开始
请求锁定(“运动员年龄”:新。运动员编号);
对于r_,在csr_竞争循环中竞争
如果(r_compete.disciply_code=‘BASKETBALL’
和(:new.atternate_dob为空
或(trunc(sysdate),:new.athletor_dob)/12<18)之间的月份
然后
提出申请错误(-20000,“运动员必须年满18岁才能参加篮球比赛”);
如果结束;
如果结束;
结束;

您可以扩展IF条件以检查不同学科的不同年龄。

错误/问题是?(不要说“不起作用”)为什么不使用检查约束而不是触发器?检查约束只能查看正在插入/更新的行中的数据,并且必须始终为true或false,因此不能使用SYSDATE。一种方法可能是将运动员的D.O.B.复制到
Competies
表中(并使用RI保持同步),并添加另一个日期列以将其与-例如,比赛日期进行比较。
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;