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