我有一张桌子:
Athlete
:
Athlete_NO (PK) | Athlete_DOB |
和
Competes
:
Athlete_NO (PFK) | Discipline_Code |
和
Discipline
:
Discipline_Code (PK) | Discipline_Name |
我试图编写一个触发器,该触发器不允许为某些学科插入18岁以下的运动员。篮球必须是18岁以上
我正在使用Oracle SQL Developer
感谢任何帮助( - :
我面临的问题是关注" IF" 18岁以下某些学科的代码。
答案 0 :(得分:0)
尝试这个,但尚未测试
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;
答案 1 :(得分:0)
您需要在所涉及的表上提供完整性约束的触发器,即Athlete和Competes。
为了使用触发器正确创建此验证,应创建一个过程以获取用户指定的锁,以便在多用户环境中正确地序列化验证。
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;
和
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;
您可以扩展IF条件以检查不同学科的不同年龄。