[英]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.