使用job模擬定時從元數據表中抽取指定數據進入目標表的過程。
一、創建元數據表
--create table test_origianl
create table test_original_data(
id number(10,2) primary key,
name varchar2(200),
descCont varchar2(100),
dateType char(5)
);
二、元數據表中插入數據
insert into test_original_data values(2.9,'name1','desc1','int');
insert into test_original_data values(3.0,'name2','desc2','long');
insert into test_original_data values(2.8,'name3','desc3','float');
insert into test_original_data values(2.6,'name4','desc4','do');
insert into test_original_data values(2.1,'name223','desc33','float');
insert into test_original_data values(5.12,'name22r34','desc3r34','float');
三、提交事務
commit;
四、創建目標表
---create table
為保持與元數據表相同的表結構,使得元數據表中的記錄可以不做任何修改直接插入目標表中,采用CTAS的方式創建目標表。
create table test_destination_dat
as
select * from test_original_data where 1!=1;
只創建相同的表結構,不導入元數據表中的記錄。
五、提交事務
commit;
六、創建定時被調用的存儲過程
---- create procedure
create or replace procedure job_test_pro
authid current_user
as
begin
--先truncate table清空原來的數據,重新把符號條件的數據導入(此處使用truncate在大數據量的情況下戲劇化的提高效率)
execute immediate 'truncate table test_destination_dat';
insert into test_destination_dat (select * from test_original_data where dateType='float' );
exception
when others then
dbms_output.put_line('errorMsg'||SQLERRM||'errorCode'||SQLCODE);
end job_test_pro;
注:1、在存儲過程中一般是沒有create table 、truncate table的權限的。如果在存儲過程中直接使用語句truncate table test_destination_dat會報錯,不能執行該語 句。 在存儲過程一般是不能直接使用create table,truncate table這類似的語句的,如果要使用這些語句必須使用excute immediate + 所要執行的sql語句來實現。
2、Authid Current_User:
這個語句比較重要,如果我們在創建存儲過程的時候不添加這條語句執行該存儲過程將不會成功,原因是默認情況存儲過程是沒有Create table,truncate table等 權限的,即使當前用戶有DBA的權限也不行,如果存儲過程中存在創建表、截斷表的操作,可以有以下兩種方式來解決該問題。
(1) 顯示的賦予該用戶Create table的權限,grant create table to user.
(2) 在存儲過程中使用Authid Current_User 標識使用當前用戶的權限。
七、創建job
1、定義job名稱
variable job2014 number ---定義在oracle中自動生成job的序號的數據類型對應到dba_jobs的數據字典中的字段job的值。現在job值為41對應名稱為job2014數 據類型為number
2、將job注冊到dba_jobs表中定時啟動job調用存儲過程
begin
dbms_job.submit(:job2014,'JOB_TEST_PRO;',sysdate,'sysdate+1/1440');
end;
/
commit;
注意:dbms_job.submit()方法的定義如下
sys.dbms_job.submit(job => :jobno,
what => 'myProc;myProcs;myProcss(''測試'');',//用分號將多個存儲過程分開,有參數的話直接寫就可以了
next_date => to_date('07-04-2011 22:00:00', 'dd-mm-yyyy hh24:mi:ss'),
interval => 'sysdate+1');
1、這里需要注意的是,在submit方法的前面一定要先定義job這個變量
2、submit方法的第二個參數是一個存儲過程的名,記得在后面添加“;”號
3、在next_date是一個時間類型變量而不是一個字符串,所以需要注意不要把它當成字符串,不需要對該參數加引號
4、最后一個參數interval是一個字符串類型,記得添加引號
5、第一個參數格式為:jobno,目的是綁定job和存儲過程。
6、最常見的錯誤如下所示:ORA-01008: not all variables bound就是沒有定義變量的意思。一定記的在使用submit方法時定義jobno變量。
7、下面是常有的設置Interval的方法:
每天固定時間運行,比如早上8點:Trunc(Sysdate+1) + 8/24
每天:trunc(sysdate+1)
每周:trunc(sysdate+7)
每月:trunc(sysdate+30)
每個星期日:next_day(trunc(sysdate),’SUNDAY’)
每天6點:trunc(sysdate+1)+6/24
半個小時:sysdate+30/1440
8、聲明變量和綁定job變量到存儲過程並注冊到dba_jobs表中必須在sqlplus下執行,在plsqldevloper中不能成功運行。
八、job異常情況處理
JOB不能運行情況處理
1.先來了解一下JOB的參數說明:與job相關的參數一個是job_queue_processes,這個是運行JOB時候所起的進程數,當然系統里面JOB大於這個數值后,就會有排 隊等候的,最小值是0,表示不運行JOB,最大值是36,在OS上對應的進程時SNPn,9i以后OS上管理JOB的進程叫CJQn.可以使用下面這個SQL確定目前有幾個SNP/C JQ在運行。
select * from v$bgprocess,這個paddr不為空的snp/cjq進程就是目前空閑的進程,有的表示正在工作的進程。
另外一個是job_queue_interval,范圍在1——3600之間,單位是秒,這個是喚醒JOB的process,因為每次snp運行完他就休息了,需要定期喚醒他,這個值不能 太小,太小會影響數據庫的性能。
2.診斷:先確定上面這兩個參數設置是否正確,特別是第一個參數,設置為0了,所有JOB就不會跑,確認無誤后,我們繼續向下。
3.使用下面的SQL察看JOB的的broken,last_date和next_date,last_date是指最近一次job運行成功的結束時間,next_date是根據設置的頻率計算的下次執行 時間,根據這個信息就可以判斷JOB上次是否正常,還可以判斷下次的時間對不對,SQL如下:
select * from dba_jobs
有時候我們發現他的next_date是4000年1月1日,說明job要不就是在running,要不就是狀態是break(broken=Y),如果發現JOB的broken值為Y,找用戶了解 一下,確定該JOB是否可以broken,如果不能broken,那就把broken值修改成N,修改再使用上面的SQL察看就發現他的last_date已經變了,JOB即可正常運行, 修改broken狀態的SQL如下:
declare
BEGIN
DBMS_JOB.BROKEN(<JOB_ID>,FALSE);
END;
4.使用下面的SQL查詢是否JOB還在Running
select * from dba_jobs_running
如果發現JOB已經Run了很久了還沒有結束,就要查原因了。一般的JOB running時會鎖定相關的相關的資源,可以查看一下v$access和v$locked_object這兩個v iew,如果發現其他進程鎖定了與JOB相關的Object,包括PKG/Function/Procedure/Table等資源,那么就要把其他進程刪除,有必要的話,把JOB的進程也刪除 ,再重新跑看看結果。
5.如果上面都正常,但是JOB還不run,怎么辦?那我們要考慮把JOB進程重啟一次,防止是SNP進程死了造成JOB不跑,指令如下:
alter system set job_queue_processes=0 ——關閉job進程,等待5——10秒鍾
alter system set job_quene_processes=5 ——恢復原來的值
九、手動運行job的指令
begin
dbms_job.run(:job2014);
end;
/
十、刪除job
begin
dbms_job.remove(:job2014);
end;
/
十一、查看job相關視圖及各字段的注解
select job,last_date,last_sec,broken,failures,interval, what from dba_jobs
詳解 dba_jobs中幾個比較重要的字段
job: 指的是job的id號。比如上面的 41
failures:job執行的時候失敗次數,如果超過了15次,那么broken列將被標為Y,以后就不會運行該job了
broken:默認為N,如果為Y,意味着不再執行該job!
interval:執行job的間隔時間。
what:該job的實際工作。
總結:模擬定時從元數據表中抽取指定類型的數據添加到目標表中,用定時job調用存儲過程。