1 --定义包中函数的纯度级别 2 create or replace package purityTest is 3 type dept_typ is table of dept%rowtype index by binary_integer; 4 dept_tab dept_typ; 5 procedure newdept( 6 p_deptno dept.deptno%type, 7 p_dname dept.dname%type, 8 p_loc dept.loc%type 9 ); 10 function getraisedsalary (p_empno emp.empno%type) 11 return number; 12 pragma restrict_references(newdept,WNPS); 13 pragma restrict_references(getraisedsalary,WNDS); 14 end puritytest; 15 wnds:不能修改数据库数据, 即禁止DML操作 16 wnps:不能修改包变量 17 rnds: 不能读取数据库,禁止执行select操作 18 rnps: 不能将包变量赋给其他值 19 --包权限 20 grant execute on scott.puritytest to userb; 21 22 23 Oracle内部提供的在数据库内部和应用程序间通信的方式有两种 24 --DBMS_PIPE管道权限赋予scott 25 grant execute on dbms_pipe to scott; 26 --管道在不同模式中传递消息 27 create or replace procedure sen_pipe_message(pipename varchar2,message 28 varchar2) is flag int; 29 begin flag:=dbms_pipe.create_pipe(pipename); --创建管道 30 if flag=0 then --如果创建管道成功 31 dbms_pipe.pack_message(message); --将消息存到本地缓冲区 32 flag:=dbms_pipe.send_message(pipename); 33 --将本地缓冲区中的消息发送到管道 34 end if; 35 end; 36 37 -- 从管道中接受消息 38 create or replace procedure receive_pipe_message 39 (pipename varchar2,message out varchar2) 40 is flag int; 41 begin 42 flag:=dbms_pipe.receive_message(pipename); 43 if flag=0 then 44 dbms_pipe.unpack_message(message); 45 flag:=dbms_pipe.remove_pipe(pipename); 46 end if; 47 end; 48 49 --scott 50 begin 51 sen_pipe_message('pipe_demo','向管道中发送一条消息'); 52 end; 53 grant execute on scott.receive_pipe_message to userb; 54 --userb 55 declare 56 v_message varchar2(100); 57 begin 58 scott.receive_pipe_message('pipe_demo',v_message); 59 dbms_output.put_line(v_message); 60 end; 61 62 63 --DBMS_ALTER包 64 grant execute on dbms_alert to scott; 65 多个会话可以并发执行同一个报警,每个会话发布报警时会阻塞其他会话 66 发布报警, 直到报警被提交, 事务会以序列的方式发生. 67 --产生报警示例 68 declare 69 v_alertname varchar2(30) :='alert_demo'; 70 begin 71 dbms_alert.signal(v_alertname,'这是一个报警消息!'); 72 commit; 73 end; 74 75 --等待报警示例,用两个会话测试 76 declare 77 v_alertname varchar2(30) :='alert_demo'; --报警名称 78 v_status integer; --等待状态 79 v_msg varchar2(200); --报警消息 80 begin 81 --注册报警, 指定名字 82 dbms_alert.register(v_alertname); 83 --监听报警,等待报警发生 84 dbms_alert.waitone(v_alertname,v_msg,v_status ); 85 --如果不返回0,则表示报警失败 86 if v_status !=0 87 then 88 dbms_output.put_line('error'); 89 end if; 90 dbms_output.put_line(v_msg); 91 end; 92 93 94 DBMS_JOB:安排和管理作业队列。通过作业队列,可以让Oracle数据库定期执行特定的任务。 95 当使用DBMS_JOB管理作业的时候,必须确保设置了初始化参数JOB_QUEUE_PROCESSES(不能为0)。 96 ALTER SYSTEM SET job_queue_processes=39 SCOPE=SPFILE; --DBA 97 select job,next_date,next_sec,INTERVAL,what from user_jobs where job=23;--查询job信息 98 99 1、 SUBMIT 100 该过程用于建立一个新的作业,当建立作业的时候,需要通过设置相应的参数来告诉Oracle要执行的内容, 101 要执行的时间,要执行任务的间隔。 102 103 DBMS_JOB.SUBMIT( 104 JOB OUT BINARY_INTERGER, --用于指定作业编号 105 WHAT IN VARCHAR2, --用于指定作业要执行的操作 106 NEXT_DATE IN DATE DEFAULT SYSDATE, --用于指定该操作的下一次运行的日期 107 INTERVAL IN VARCHAR2 DEFAULT ‘NULL’, --用于指定该操作的时间间隔 108 NO_PARSE IN BOOLEAN DEFAULT FALSE, --用于指定是否需要解析与作业相关的过程 109 INSTANCE IN BINARY_INTEGER DEFAULT ANY_INSTANCE, --用于指定哪个例程可以运行作业? 110 FORCE IN BOOLEAN DEFAULT FALSE --用于指定是否强制运行与作业相关的例程 111 ); 112 113 114 建立Oracle作业的例子: 115 DECLARE 116 JOBNO NUMBER; --通过查看该变量可以得到返回的作业编号 117 BEGIN 118 DBMS_JOB.SUBMIT(JOBNO,'PRC_SENDTOGX;',SYSDATE,'SYSDATE+1'); --执行工信局提供数据的脚本程序 119 END; 120 121 interval参数值 122 每天午夜12点: 'TRUNC(SYSDATE + 1)' 123 每天早上8点30分 'TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)' 124 每星期二中午12点 'NEXT_DAY(TRUNC(SYSDATE ), ''TUESDAY'' ) + 12/24' 125 每个月第一天的午夜12点 'TRUNC(LAST_DAY(SYSDATE ) + 1)' 126 每个季度最后一天的晚上11点 'TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), 'Q' ) -1/24' 127 每分钟执行一次 'SYSDATE+1/1440' 128 129 2、 REMOVE 130 这个过程的作用是用于删除作业队列当中的特定的作业,它的语法如下: 131 DBMS_JOB.REMOVE(JOB IN BINARY_INTEGER); 132 下面是一个删除作业的例子: 133 首先查看DBA_JOBS表,看表里面有哪些任务正在执行着? 134 SELECT * FROM DBA_JOBS; 135 可以看到里面的JOB就是我们要删除的作业的编号,LOG_USER是创建该任务的人。 136 SQL> EXEC DBMS_JOB.REMOVE(467); 137 SQL>COMMIT; 138 这样就能把已经建立的作业删除了。 139 140 3、 CHANGE 141 该过程改变与作业相关的所有的信息,其中包括作业的操作内容,作业运行的时间以及运行时间间隔信息等等。语法如下: 142 DBMS_JOB.CHANGE( 143 JOB IN BINARY_INTEGER, 144 WHAT IN VARCHAR2, 145 NEXT_DATE, 146 INTERVAL IN VARCHAR2, 147 INSTANCE IN BINARY_INTEGER DEFAULT NULL, 148 FORCE IN BOOLEAN DEFAULT FALSE 149 ); 150 151 例子: 152 SQL>EXEC DBMS_JOB.CHANGE(2,NULL,NULL,’SYSDATE+2’); 153 SQL>COMMIT; 154 155 4、 WHAT 156 WHAT用来改变作业要执行的操作,例如: 157 SQL>EXEC DBMS_JOB.WHAT(268,’BEIGN FUNCTION(8);END;’); 158 159 5、 NEXT_DATE 160 用来改变作业的下次运行日期 161 SQL>EXEC DBMS_JOB.NEXT_DATE(‘478’,’SYSDATE+2’); 162 163 6、 INTERVAL 164 该过程用来改变作业的运行时间间隔,下面的运行时间间隔修改为每分钟执行一次: 165 SQL>exec dbms_job.interval(478,’SYSDATE+1/24/60 166 167 7、BROKEN 168 该过程用于给该作业打上中断标志,可以在DBA_JOBS表里面观察该作业的BROKEN标志知否为中断。例子: 169 SQL>EXEC DBMS_JOB.BROKEN(478,TRUE); 170 SQL>COMMIT; 171 172 8、RUN 173 该过程用来执行该作业,例子: 174 SQL>EXEC DBMS_RN(478); 175 SQL>COMMIT; 176 177 1、 如何停止一个作业? 178 SQL>DBMS_JOBS.BROKEN(2,TRUE); 179 SQL>COMMIT; 180 181 2、如何启动一个作业? 182 SQL>DBMS_JOBS.BROKEN(2,FALSE); 183 SQL>COMMIT; 184 185 3、 如何计算一个过程运行的时间(DATE和TimeStamp)? 186 187 可以在过程的开始设置一个时间,然后在过程的结尾处设置一个时间,然后两个时间的时间差可以计算出该过程运行的时间。通过实践发现使用SYSESTAMP来计算时间比较准确一些: 188 189 SELECT to_char(systimestamp,'yyyy-mm-dd hh24:mi:ss:ff4') FROM dual; 190 191 DBMS_SCHEDULER [ˈskɛdʒʊələ] Oracle调度 192 BEGIN 193 DBMS_SCHEDULER.CREATE_JOB ( 194 job_name => 'job_do_main_rtt', 195 job_type => 'STORED_PROCEDURE', 196 job_action => 'com_job.docachezmondate', 197 start_date => sysdate, 198 repeat_interval => 'FREQ=SECONDLY;INTERVAL=1', 199 comments => '每3秒汇总主界面的统计数据' 200 ); 201 END; 202 203 begin 204 dbms_scheduler.create_job( 205 job_name => , 206 job_type => , 207 jog_action => , 208 number_of_arguments => , 209 start_date => , 210 repeat_interval => , 211 end_date => , 212 job_class => , 213 enabled => , 214 auto_drop => , 215 comments => 216 ); 217 end; 218 219 参数介绍: 220 job_name:job名字 221 job_type:job类型,支持三种类型: 222 1)PLSQL_BLOCK——PL/SQL语句块; 223 2)STORED_PROCEDURE——存储过程; 224 3)EXECUTABLE——外部程序(外部程序可以是一个shell脚本,也可以是操作系统级别的指令)。 225 job_action:根据job_type的不同,job_action有相对应的内容。 226 number_of_arguments:参数个数。 227 start_date:执行开始时间。 228 repeat_interval:指定job执行频率(如每分钟执行一次、每天执行一次等)。 229 end_date:执行结束时间。 230 job_class:jobclass的名字。 231 enabled:指定是否自动激活job,为true代表自动激活,false代表不激活。 232 auto_drop:执行完是否自动drop 233 comments:对于job的简单说明 234 235 236 FREQ 关键字用来指定间隔的时间周期,可选参数有:YEARLY(年), MONTHLY(月), WEEKLY(周), DAILY(日), HOURLY(时), MINUTELY(分), SECONDLY(秒)等单位。 237 238 INTERVAL 关键字用来指定间隔的频繁,可指定的值的范围从1-999。 239 240 BYHOUR 指定一天中的小时。可指定的值的范围从1-24。16,17,18就表示每天下午的4、5、6点。 241 BYDAY 关键字用来指定每周的哪天运行。 242 BYMONTHDAY 关键字用来指定每月中的哪一天。-1 表示每月最后一天。 243 BYMONTH 关键字用来指定每年的月份。 244 BYDATE 指定日期。0310就表示3月10日。 245 246 例如: 247 运行每星期五。(所有这三个例子是等价的。) 248 FREQ=DAILY; BYDAY=FRI; 249 FREQ=WEEKLY; BYDAY=FRI; 250 FREQ=YEARLY; BYDAY=FRI; 251 252 设置任务隔一周运行一次,并且仅在周5运行: 253 FREQ=WEEKLY; INTERVAL=2; BYDAY=FRI; 254 255 在每月的最后一天运行 256 FREQ=MONTHLY; BYMONTHDAY=-1; 257 258 三月十日开。(两个例子是等价的) 259 FREQ=YEARLY; BYMONTH=MAR; BYMONTHDAY=10; 260 FREQ=YEARLY; BYDATE=0310; 261 262 设置任务每10隔天运行: 263 REPEAT_INTERVAL => 'FREQ=DAILY; INTERVAL=10'; 264 265 设置任务在每天的下午4、5、6点时运行: 266 REPEAT_INTERVAL => 'FREQ=DAILY; BYHOUR=16,17,18'; 267 268 设置任务在每月29日运行: 269 REPEAT_INTERVAL => 'FREQ=MONTHLY; BYMONTHDAY=29'; 270 271 设置任务在每年的最后一个周5运行: 272 REPEAT_INTERVAL => 'FREQ=YEARLY; BYDAY=-1FRI'; 273 274 设置任务每隔50个小时运行: 275 REPEAT_INTERVAL => 'FREQ=HOURLY; INTERVAL=50'; 276 277 repeat_interval => 'FREQ=HOURLY; INTERVAL=2' 278 每隔2小时运行一次job 279 280 repeat_interval => 'FREQ=DAILY' 281 每天运行一次job 282 283 repeat_interval => 'FREQ=WEEKLY; BYDAY=MON,WED,FRI" 284 每周的1,3,5运行job 285 286 repeat_interval => 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=30; 287 每年的3,6,9,12月的30号运行job 288 289 290 对job的各种操作查询: 291 select owner, job_name, state from dba_scheduler_jobs; 292 select job_name, state from user_scheduler_jobs; 293 294 注意:相应的查询都需要有相对应的权限。 295 运行:dbms_scheduler.run_job('job_name'); 296 停止:dbms_scheduler.stop_job('job_name'); 297 删除:dbms_scheduler.drop_job('job_name') 298 299 300 /* 301 ** 创建一个存储过程,输出当前系统时间 302 */ 303 create or replace procedure My_Time 304 is 305 begin 306 dbms_output.put_line(to_char(sysdate, 'yyyy-mm-hh HH24:MI:SS')); 307 end; 308 309 /* 310 ** 创建一个job来调用以上存储过程 311 */ 312 declare 313 n_JobExist integer; --标记job是否存在 314 s_Job_Name varchar2(32) := 'My_Job'; 315 begin 316 n_JobExist := 0; 317 --查询My_Job是否存在,如果存在则先drop掉 318 begin 319 select 1 into n_JobExist from user_scheduler_jobs 320 where job_name = upper(s_Job_Name); 321 exception 322 when NO_DATA_FOUND then 323 NULL; 324 end; 325 if (n_JobExist = 1) then 326 sys.dbms_scheduler.drop_job(s_Job_Name); 327 end if; 328 --创建My_Job 329 sys.dbms_scheduler.create_job( 330 job_name => s_Job_Name, 331 job_type => 'plsql_block', 332 --要调用的存储过程 333 job_action => 'begin My_Time; end;', 334 repeat_interval => 'freq=MINUTELY;interval=1', 335 start_date => sysdate, 336 --end_date => sysdate + 3/(24*60), 337 job_class => 'DEFAULT_JOB_CLASS', 338 auto_drop => false, 339 enabled => true 340 ); 341 end;