临回家了,把这两天搞的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