Oracle触发器-校验身份证和字节长度

一、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;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醉梦洛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值