zoukankan      html  css  js  c++  java
  • oracle触发器的使用(二)

      临回家了,把这两天搞的oracle的点东西,放到博客上,主要是触发器的使用,没有涉及到具体复杂的业务,但是都是比较实际的业务需求。实际中能够用的上,主要是用于审计,用户实际业务需求(友好性的考虑),与view等配合使用等。直接上code吧,在pl/sql中执行相应的模块就能得到相应的结果,注释和清晰,主要是看书一步步搞的。有的自己备用方便。如果有用,大家也可以看看。

      1 --好的创建表的方法
      2 DECLARE
      3   TB NUMBER;
      4 BEGIN
      5   SELECT COUNT(*) INTO TB FROM TABS WHERE TABLE_NAME = 'FRAME';
      6   IF TB <> 0 THEN
      7     EXECUTE IMMEDIATE 'DROP TABLE frame';
      8     EXECUTE IMMEDIATE '
      9     CREATE TABLE frame
     10     (
     11        bowler_id number,
     12        game_id number,
     13        frame_id number,
     14        strike varchar2(1) default ''N'',
     15        spare varchar2(1) default ''N'',
     16        score number,
     17        constraint frame_pk
     18        primary key (bowler_id,game_id,frame_id)
     19     )';
     20     DBMS_OUTPUT.PUT_LINE('存在该表已删除,并创建新的表');
     21   ELSE
     22     EXECUTE IMMEDIATE 'CREATE TABLE frame
     23     (
     24        bowler_id number,
     25        game_id number,
     26        frame_id number,
     27        strike varchar2(1) default ''N'',
     28        spare varchar2(1) default ''N'',
     29        score number,
     30        constraint frame_pk
     31        primary key (bowler_id,game_id,frame_id)
     32     )';
     33     DBMS_OUTPUT.PUT_LINE('不存在该表,已创建新表');
     34   END IF;
     35 END;
     36 
     37 --创建审计表
     38 DECLARE
     39   TB NUMBER;
     40 BEGIN
     41   SELECT COUNT(*) INTO TB FROM TABS WHERE TABLE_NAME = 'FRAME_AUDIT';
     42   IF TB <> 0 THEN
     43     EXECUTE IMMEDIATE 'DROP TABLE frame_audit';
     44     EXECUTE IMMEDIATE '
     45     CREATE TABLE frame_audit
     46     (
     47            bowler_id NUMBER,
     48            game_id NUMBER,
     49            frame_id NUMBER,
     50            old_strike VARCHAR2(1),
     51            new_strike VARCHAR2(1),
     52            
     53            old_spare VARCHAR2(1),
     54            new_spare VARCHAR2(1),
     55            
     56            old_score number,
     57            new_score number,
     58            
     59            change_date DATE,
     60            operation VARCHAR2(6) 
     61     )';
     62     DBMS_OUTPUT.PUT_LINE('存在该表已删除,并创建新的表');
     63   ELSE
     64     EXECUTE IMMEDIATE 'CREATE TABLE frame_audit
     65                   (
     66                          bowler_id NUMBER,
     67                          game_id NUMBER,
     68                          frame_id NUMBER,
     69                          old_strike VARCHAR2(1),
     70                          new_strike VARCHAR2(1),
     71                          
     72                          old_spare VARCHAR2(1),
     73                          new_spare VARCHAR2(1),
     74                          
     75                          old_score number,
     76                          new_score number,
     77                          
     78                          change_date DATE,
     79                          operation VARCHAR2(6) 
     80                   )';
     81     DBMS_OUTPUT.PUT_LINE('不存在该表,已创建新表');
     82   END IF;
     83 END;
     84 
     85 
     86 --创建触发器
     87 CREATE OR REPLACE TRIGGER audit_frames
     88 AFTER INSERT OR UPDATE OR DELETE ON frame
     89 FOR EACH ROW
     90   BEGIN
     91     IF inserting THEN
     92       INSERT INTO frame_audit(bowler_id,game_id,frame_id,
     93        new_strike,new_spare,
     94        new_score,change_date,operation)
     95       VALUES(:new.bowler_id,:new.game_id,:new.frame_id,:new.strike,:new.spare,:new.score,SYSDATE,'insert');
     96       
     97       ELSIF updating THEN
     98       INSERT INTO frame_audit(bowler_id,game_id,frame_id,
     99       old_strike,new_strike,old_spare,new_spare,
    100       old_score,new_score,change_date,operation)
    101       VALUES(:new.bowler_id,:new.game_id,:new.frame_id,:old.strike,:new.strike,:old.spare,:new.spare,:old.score,:new.score,SYSDATE,'update');
    102       
    103       ELSIF deleting THEN
    104       INSERT INTO frame_audit(bowler_id,game_id,frame_id,
    105        old_strike,old_spare,
    106        old_score,change_date,operation)
    107       VALUES(:old.bowler_id,:old.game_id,:old.frame_id,:old.strike,:old.spare,:old.score,SYSDATE,'insert');
    108       
    109       END IF;
    110       END audit_frames;
    111 
    112 --在创建之后,后来使用的时候报了一个触发器无效且未通过认证的错误
    113 --解决办法是找到触发器-》右键查看-》找到相应的错误(insert->inserting).问题解决。
    114 
    115 
    116 INSERT INTO frame (bowler_id,game_id,frame_id,strike)
    117 VALUES (1,2,3,'y');
    118 
    119 
    120 SELECT * FROM frame;
    121 
    122 UPDATE frame SET strike ='N',
    123 spare = 'y'
    124 WHERE bowler_id =1
    125 AND game_id =2
    126 AND frame_id =3;
    127 
    128 DELETE frame WHERE bowler_id = 1;
    129 
    130 COMMIT;
    131 SELECT * FROM frame;
    132 SELECT * FROM frame_audit;
    133 
    134 /*创建更加有针对性的触发器:只是在修改记录的时候触发*/
    135 /*************Begin*****************/
    136 CREATE OR REPLACE TRIGGER audit_update
    137 AFTER UPDATE OF strike,spare ,score ON frame
    138 REFERENCING OLD AS prior_to_cheat NEW AS after_cheat
    139 FOR EACH ROW
    140   WHEN (
    141     prior_to_cheat.strike != after_cheat.strike
    142     OR prior_to_cheat.spare != after_cheat.spare
    143     OR prior_to_cheat.score != after_cheat.score)
    144     BEGIN 
    145       INSERT INTO frame_audit(bowler_id,game_id,frame_id,
    146       old_strike,new_strike,old_spare,new_spare,
    147       old_score,new_score,change_date,operation)
    148       VALUES(:prior_to_cheat.bowler_id,:prior_to_cheat.game_id,:prior_to_cheat.frame_id,:after_cheat.strike,:prior_to_cheat.strike,:after_cheat.spare,:prior_to_cheat.spare,:after_cheat.score,:prior_to_cheat.score,SYSDATE,'update');
    149     END;
    150 --测试语句
    151 INSERT INTO frame (bowler_id,game_id,frame_id,strike)
    152 VALUES (1,1,1,'y');
    153 UPDATE frame SET strike = strike;
    154 SELECT * FROM frame;
    155 SELECT * FROM frame_audit;
    156 /********************END**************************/
    157 
    158 /***********************************/
    159 --增加有好性,在击球全中和2次全中的选手加10分
    160 /***************BEGIN*****************/
    161 
    162 CREATE OR REPLACE TRIGGER set_score
    163 BEFORE INSERT ON frame
    164 FOR EACH ROW
    165   WHEN (NEW.score IS NOT NULL)
    166     BEGIN
    167       IF :New.strike ='y' OR :new.spare = 'y'
    168         THEN 
    169           :new.score := :new.score+10;
    170       END IF;
    171   END;
    172       
    173 --测试语句
    174 INSERT INTO frame (bowler_id,game_id,frame_id,strike,score)
    175 VALUES (2,2,1,'y',10);
    176 
    177 INSERT INTO frame (bowler_id,game_id,frame_id,strike,score)
    178 VALUES (2,2,2,'y',9);
    179 
    180 INSERT INTO frame (bowler_id,game_id,frame_id,strike,score)
    181 VALUES (3,1,1,'n',9);
    182 SELECT * FROM frame;
    183 SELECT * FROM frame_audit;
    184 /*****************分数校验***********/
    185 CREATE OR REPLACE TRIGGER validate_score
    186 AFTER INSERT OR UPDATE ON frame
    187 FOR EACH ROW
    188   BEGIN 
    189     IF :New.strike ='y' AND :new.score <10
    190       THEN 
    191         raise_application_error(-20001,'ERROR:score for strike must be >=10');
    192         ELSIF :new.spare ='y' AND :new.score<10
    193         THEN 
    194           raise_application_error(-20001,'ERROR:Score for spare must be >=10');
    195           ELSIF :new.strike ='y' AND :new.spare = 'y'
    196           THEN
    197             raise_application_error(-20001,'ERROR: Cannot Enter Spare and strike');
    198             
    199       END IF;
    200     END;
    201     --测试语句
    202 INSERT INTO frame (bowler_id,game_id,frame_id,strike,score)
    203 VALUES (5,1,1,'y',6);
    204  
    205 SELECT * FROM frame;
    206 SELECT * FROM frame_audit;       
    207 /**************END********************/
    208 
    209 /***********************************/
    210 /**********************************/
    211 /**********一个简单的快递系统******************/
    212 /**********************************/
    213 /********************************/
    214 --如果表存在删除表让后再创建,不存在直接创建表
    215 DECLARE
    216   I INTEGER;
    217 BEGIN
    218   SELECT COUNT(*) INTO I FROM USER_TABLES WHERE TABLE_NAME = 'DELIVERY'; --注意表名大写
    219   IF I > 0 THEN
    220     DBMS_OUTPUT.PUT_LINE('该表已存在!删除后,创建表');
    221     EXECUTE IMMEDIATE 'DROP TABLE DELIVERY';
    222   ELSE
    223     DBMS_OUTPUT.PUT_LINE('该表不存在,创建表');
    224   END IF;
    225   EXECUTE IMMEDIATE 'CREATE TABLE delivery
    226                     (
    227                            delivery_id NUMBER,
    228                            delivery_start DATE,
    229                            delivery_end DATE,
    230                            area_id NUMBER,
    231                            driver_id NUMBER
    232                     )';
    233   END;       
    234 --测试语句
    235   SELECT * FROM delivery;
    236 --创建area表  
    237 DECLARE
    238   I INTEGER;
    239 BEGIN
    240   SELECT COUNT(*) INTO I FROM USER_TABLES WHERE TABLE_NAME = 'AREA'; --注意表名大写
    241   IF I > 0 THEN
    242     DBMS_OUTPUT.PUT_LINE('该表已存在!删除后,创建表');
    243     EXECUTE IMMEDIATE 'DROP TABLE AREA';
    244   ELSE
    245     DBMS_OUTPUT.PUT_LINE('该表不存在,创建表');
    246   END IF;
    247   EXECUTE IMMEDIATE 'CREATE TABLE area
    248                     (
    249                            area_id NUMBER,
    250                            area_desc varchar(30)
    251                     )';
    252 END;  
    253 --测试语句  
    254 SELECT * FROM area;
    255 
    256 --创建driver表
    257  DECLARE
    258   I INTEGER;
    259 BEGIN
    260   SELECT COUNT(*) INTO I FROM USER_TABLES WHERE TABLE_NAME = 'DRIVER'; --注意表名大写
    261   IF I > 0 THEN
    262     DBMS_OUTPUT.PUT_LINE('该表已存在!删除后,创建表');
    263     EXECUTE IMMEDIATE 'DROP TABLE DRIVER';
    264   ELSE
    265     DBMS_OUTPUT.PUT_LINE('该表不存在,创建表');
    266   END IF;
    267   EXECUTE IMMEDIATE 'CREATE TABLE driver
    268                     (
    269                            driver_id NUMBER,
    270                            driver_name varchar2(30)
    271                     )';
    272 END; 
    273 --测试语句
    274 SELECT * FROM driver; 
    275 
    276 --创建3个序列为表提供唯一标识符
    277 CREATE SEQUENCE delivery_id_seq;
    278 CREATE SEQUENCE area_id_seq;
    279 CREATE SEQUENCE driver_id_seq;
    280 
    281 --用一个视图同时显示信息
    282 CREATE OR REPLACE VIEW delivery_info AS
    283 SELECT d.delivery_id,
    284        d.delivery_start,
    285        d.delivery_end,
    286        a.area_desc,
    287        dr.driver_name
    288         FROM delivery d ,area a,driver dr
    289         WHERE a.area_id = d.area_id
    290         AND dr.driver_id = d.driver_id;
    291         
    292 --创建instead of insert 触发器
    293 CREATE OR REPLACE TRIGGER delivery_info_insert
    294 INSTEAD OF INSERT
    295 ON delivery_info
    296 DECLARE 
    297 --cursour to get the driver by name
    298 CURSOR curs_get_driver_id (cp_driver_name VARCHAR2)
    299 IS 
    300 SELECT driver_id
    301 FROM
    302 driver
    303 WHERE driver_name = cp_driver_name;
    304 v_driver_id NUMBER;
    305 --cursor to get area by name
    306 CURSOR curs_get_area_id (cp_area_desc VARCHAR2)
    307 IS
    308 SELECT area_id
    309 FROM area
    310 WHERE area_desc =cp_area_desc;
    311 
    312 v_area_id NUMBER;
    313 BEGIN
    314 /*make sure the delivery_end value is null */  
    315 
    316 IF :new.delivery_end IS NOT NULL
    317   THEN
    318     raise_application_error(-20000,'Delivery end date value must be null when delivery created');
    319 END IF;
    320 
    321 /*try to get the driver id by the name if not found
    322 *then create a new brand driver id from the sequence 
    323 **/
    324 OPEN curs_get_driver_id(UPPER(:new.driver_name));
    325 
    326 FETCH curs_get_driver_id INTO v_driver_id;
    327 
    328 IF curs_get_driver_id %NOTFOUND
    329   THEN 
    330     SELECT driver_id_seq.nextval
    331     INTO v_driver_id
    332     FROM dual;
    333     
    334     INSERT INTO driver
    335     (
    336     driver_id,driver_name
    337     )
    338     VALUES (v_driver_id,UPPER(:new.driver_name));
    339 END IF;
    340 
    341 CLOSE curs_get_driver_id;
    342 /*try to get the area id by the name if not found
    343 *then create a new brand area id from the sequence
    344 **/
    345 
    346 OPEN curs_get_area_id(UPPER(:new.area_desc));
    347 
    348 FETCH curs_get_area_id
    349 INTO v_area_id;
    350 IF curs_get_area_id %NOTFOUND
    351   THEN 
    352     SELECT area_id_seq.nextval
    353     INTO v_area_id
    354     FROM dual;
    355     
    356     INSERT INTO area
    357     (area_id ,area_desc)
    358     VALUES(v_area_id,UPPER(:new.area_desc));
    359 END IF;
    360 
    361 CLOSE curs_get_area_id;
    362 /*create the delivery entry
    363 */
    364 INSERT INTO delivery
    365 (delivery_id,delivery_start,delivery_end,area_id,driver_id)
    366 VALUES(delivery_id_seq.nextval,NVL(:new.delivery_start,SYSDATE),NULL,v_area_id,v_driver_id);
    367 
    368 END;
    369 
    370 /*************create instead of insert trigger end*******************************/
    371 
    372 --测试语句
    373 INSERT INTO delivery_info(delivery_id,
    374 delivery_start,delivery_end,area_desc,driver_name)
    375 VALUES (NULL,NULL,NULL,'local college','big ted');
    376 
    377 SELECT * FROM delivery;
    378 SELECT * FROM area;
    379 SELECT * FROM driver;
    380                                                                                                                                                       
  • 相关阅读:
    linux_grep操作
    linux_awk操作
    linux_sed操作
    [题解]USACO 5.2.1 Snail Trails
    [数据生成器]UVA10054 The Necklace
    [题解]UVA10054 The Necklace
    [题解]UVA11027 Palindromic Permutation
    [题解]UVA10129 Play on Words
    [题解]UVA11029 Leading and Trailing
    计蒜客NOIP2017提高组模拟赛(五)day1-机智的 AmyZhi
  • 原文地址:https://www.cnblogs.com/accipiter/p/2893429.html
Copyright © 2011-2022 走看看