一、Oracle觸發器的一個簡單介紹:
觸發器:是特定事件出現的時候,自動執行的代碼塊。類似於存儲過程,但是用戶不能直接調用他們。
功 能:
1.允許、限制對錶的修改
2.自動生成派生列,比如自增字段
3.強制數據一致性
4.提供審計和日誌記錄
5.防止無效的事務處理
6.啓用複雜的業務邏輯
觸發器的組成部分:
1.觸發器名稱
2.觸發語句
3.觸發器限制
4.觸發操作
如:
1️⃣觸發器名稱
create or replace trigger trig_etc(觸發器名稱)
命名習慣
create or replace trigger 觸發器名稱
before/after insert or update or delete on 表名
for each now
begin
if XXXX then
end if;
end;
注:這個屬於常規寫法吧!
2️⃣觸發語句
比如:
表或試圖上的DML語句
DDL語句
數據庫關閉或者啓動,startup shutdown等等。。。
before/after insert or update or delete
referencing old as old_value
new as new_value
for each row
ETC_Card 表名
card_id 列名
3️⃣觸發器限制
when (new_value.card_id<>1 )
限制不是必須的。此例表示如果列card_id不等於1的時候,觸發器就會執行。
其中的new_value是代表更新之後的值
4️⃣觸發操作
是觸發器的主體
begin
:new_value.commission_pct :=0;
end;
主體很簡單,就是將更新後的commission_pct列置爲0
二、觸發器實戰
由於業務要求,需要讓其中一個字段不能超過8個字節,兩一個字符串的第一個字節必須是1,最後一個是身份證號最後一個字節的校驗,要求是字母只能是X,不能是其他字母,數字隨意;
由此業務要求參數下面觸發器:
create or replace trigger trg_etc
--是在它插入數據之前觸發
before insert on Etc_Card_Info_New
for each row
begin
--往日誌表中插記錄
insert into ETC_LOG VALUES(systimestamp,:new.card_no || '|' || :new.AGENTNAME,'trg_etc',0,'');
--第一個要求是AGENTNAME列不能超過8個字節
if length(:NEW.AGENTNAME) > 8 then
RAISE_APPLICATION_ERROR(-20001,'經辦人姓名不能超過四個漢字!');
end if;
--第二個要求是AGENTIDTYPE列中的字符串第一個字節必須是1
if SUBSTR(:NEW.AGENTIDTYPE,1,1) <> '1' then
RAISE_APPLICATION_ERROR(-20002,'個人經辦人證件類型必須是以1開頭的');
end if;
--第三個要求是身份證合法性並且對身份證最後一個字節的校驗
if SUBSTR(:NEW.AGENTIDTYPE,1,1) = '1' then
if fn_checkidcard(:NEW.AGENTIDTYPE) = 1 then
if INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'0') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'1') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'2') = 0 or
INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'3') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'4') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'5') = 0 or
INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'6') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'7') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'8') = 0 or
INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'9') = 0 or INSTR(SUBSTR(:NEW.AGENTIDNUM,-1),'X') = 0 then
RAISE_APPLICATION_ERROR(-20003,'個人經辦人證件號碼最後一位字母只能是X!');
end if;
else
RAISE_APPLICATION_ERROR(-20004,'個人身份證號不符合規範!');
end if;
end if;
END trg_etc;
注:附上校驗身份證的Oracle函數腳本
CREATE OR REPLACE FUNCTION fn_checkidcard (p_idcard IN VARCHAR2) RETURN INT
IS
v_regstr VARCHAR2 (2000);
v_sum NUMBER;
v_mod NUMBER;
v_checkcode CHAR (11) := '10X98765432';
v_checkbit CHAR (1);
v_areacode VARCHAR2 (2000) := '11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91,';
BEGIN
CASE LENGTHB (p_idcard)
WHEN 15
THEN -- 15位
IF INSTRB (v_areacode, SUBSTR (p_idcard, 1, 2) || ',') = 0 THEN
RETURN 0;
END IF;
IF MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 2)) + 1900, 400) = 0
OR
(
MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 2)) + 1900, 100) <> 0
AND
MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 2)) + 1900, 4) = 0
)
THEN -- 閏年
v_regstr :=
'^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$';
ELSE
v_regstr :=
'^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$';
END IF;
IF REGEXP_LIKE (p_idcard, v_regstr) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
WHEN 18
THEN -- 18位
IF INSTRB (v_areacode, SUBSTRB (p_idcard, 1, 2) || ',') = 0 THEN
RETURN 0;
END IF;
IF MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 4)), 400) = 0
OR
(
MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 4)), 100) <> 0
AND
MOD (TO_NUMBER (SUBSTRB (p_idcard, 7, 4)), 4) = 0
)
THEN -- 閏年
v_regstr :=
'^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$';
ELSE
v_regstr :=
'^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$';
END IF;
IF REGEXP_LIKE (p_idcard, v_regstr) THEN
v_sum :=
( TO_NUMBER (SUBSTRB (p_idcard, 1, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 11, 1))
)
* 7
+ ( TO_NUMBER (SUBSTRB (p_idcard, 2, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 12, 1))
)
* 9
+ ( TO_NUMBER (SUBSTRB (p_idcard, 3, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 13, 1))
)
* 10
+ ( TO_NUMBER (SUBSTRB (p_idcard, 4, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 14, 1))
)
* 5
+ ( TO_NUMBER (SUBSTRB (p_idcard, 5, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 15, 1))
)
* 8
+ ( TO_NUMBER (SUBSTRB (p_idcard, 6, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 16, 1))
)
* 4
+ ( TO_NUMBER (SUBSTRB (p_idcard, 7, 1))
+ TO_NUMBER (SUBSTRB (p_idcard, 17, 1))
)
* 2
+ TO_NUMBER (SUBSTRB (p_idcard, 8, 1)) * 1
+ TO_NUMBER (SUBSTRB (p_idcard, 9, 1)) * 6
+ TO_NUMBER (SUBSTRB (p_idcard, 10, 1)) * 3;
v_mod := MOD (v_sum, 11);
v_checkbit := SUBSTRB (v_checkcode, v_mod + 1, 1);
IF v_checkbit = upper(substrb(p_idcard,18,1)) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
ELSE
RETURN 0;
END IF;
ELSE
RETURN 0; -- 身份證號碼位數不對
END CASE;
EXCEPTION
WHEN OTHERS
THEN
RETURN 0;
END fn_checkidcard;