前言~
今天莫名的接到一個任務,需要使用oracle定時任務和oracle存儲過程來每日創建一個日誌表,由於小編呢尚未接觸過存儲過程和定時任務,所以今天學習了一番,特定來總結一下。望能給予一些未接觸過存儲過程的小夥伴一些幫助。
今入今天的正題,首先要了解一下oracle的存儲過程,都有哪些結構,而plsql是一個輔助工具,是能幫助我們更輕鬆的實現存儲過程。
上述就是一個無參的存儲過程實例,一個存儲過程大體分爲這麼幾個部分:
1)、創建語句:create or replace procedure 存儲過程名稱 [authid current_user] ;
“”[]“”中括號的內容是可選的,其表示修改存儲過程,加入authid current_user時存儲過程可以使用role權限。否則會報ORA-01031權限不足。
如果沒有or replace語句,那只是新建一個存儲過程,如果系統中存在相同的存儲過程,則會報錯,Create or replace procedure 如果系統中沒有此存儲過程就新建一個,如果系統中有此存儲過程則把原來刪除掉,重新創建一個存儲過程。
存儲過程名定義:包括存儲過程名和參數列表、參數名和參數類型。參數列表可不寫,如例子所示。參數名不能重複,並且每個參數之間用分號“ ;” 隔開, 參數傳遞方式:IN, OUT, IN OUT。如下面例子所示:
下面說明一下參數傳遞方式:
in:表示輸入參數,調用存儲過程時從外面傳進來的,它的值不能修改。
out:表示輸出參數,當一個參數被指定爲OUT類型時,如果還未調用存儲過程之前對該參數進行了賦值,那麼在存儲過程中該參數的值仍然是null,但是如果在調用過程中對該參數進行賦值,那麼值不爲null。
in out:表示輸入輸出參數,它的值可以修改。
參數的數據類型只需要指明類型名即可,不需要指定寬度。參數的寬度由外部調用者決定。過程可以有參數,也可以沒有參數。
我們看到例子中存在一個“”as“”,它表示變量聲明塊,可以理解爲plsql中的declare關鍵字,用於聲明變量。除了as外,還有is。變量聲明塊用於聲明該存儲過程需要用到的變量,它的作用域爲該存儲過程。另外這裏聲明的變量必須指定寬度。遵循PL/SQL的變量聲明規範。
其中,as和is的區別:在視圖(VIEW)中只能用AS不能用IS;
在遊標(CURSOR)中只能用IS不能用AS。
過程語句塊:從begin 關鍵字開始爲過程的語句塊。存儲過程的具體邏輯在這裏來實現。
異常處理塊:關鍵字爲exception ,爲處理語句產生的異常。該部分爲可選
結束塊:由end關鍵字結果。
2)、下面講解一下參數列表中參數的默認值
通過default 關鍵字爲存儲過程的參數指定默認值。在對存儲過程調用時,就可以省略默認值。
值得注意的是:默認值僅僅支持IN傳輸類型的參數。OUT 和 IN OUT不能指定默認值
上述情況是default關鍵字修飾的是最後一個參數,如果是修飾第一個參數呢?
如果我們想使用第一個參數的默認值時,exec procdefault2('aa'); 這樣是會報錯的。
那怎麼變呢?可以指定參數的值。
SQL> exec procdefault2(p2 =>'aa'); 這樣就OK了,指定aa傳給參數p2。
3)、繼續講解存儲過程內部塊
我們知道了存儲過程的結構,語句塊由begin開始,以end結束。這些塊是可以嵌套。在語句塊中可以嵌套任何以下的塊:Declare … begin … exception … end;
需要注意變量的作用域。
4)、存儲過程中的循環
存儲過程的循環語句塊有:for...in...loop、while和loop循環。下面分別給予相關實例。
(1)、for...in...loop
實例一 循環遍歷遊標:
create or replace procedure proc_test
as
cursor c1
is
select * from dat_trade;
begin
for x in c1
loop
dbms_output.put_line (x.id);
end loop;
end proc_test;
實例二 根據數值進行循環:
create or replace procedure proc_test (v_num in NUMBER)
as
begin
for x in 1..100 loop
dbms_output.put_line (x);
end loop;
end proc_test;
實例三 在過程裏指定輸入參數 v_num. 在調用過程時指定循環次數:
create or replace procedure proc_test (v_num IN NUMBER)
as
begin
for x in 1 .. v_num
loop
dbms_output.put_line (x);
end loop;
end proc_test;
(2)、loop循環
LOOP
loop
delete from orders
where senddate < to_char (add_months (sysdate, -3),'yyyy-mm-dd') and rownum < 1000;
exit when SQL%ROWCOUNT < 1;
commit;
end loop;
這裏的 SQL%ROWCOUNT 是隱士遊標。 除了這個,還有其他幾
個:%found,%notfound, %isopen。
(3)while循環
create or replace procedure proc_test (v_num in number)
as
i number := 1;
begin
while i < v_num
loop
begin
i := i + 1;
dbms_output.put_line (i);
end;
end loop;
end proc_test;
5)、 存儲過程中的判斷
存儲過程的判斷語句塊有:if 條件語句、case ... when ... end case兩種
下面給出實例:
(1)、單if實例(if...then...end if; && if...then...else...end if;)
實例一:
create or replace procedure pro_test is
--邏輯判斷變量
exit_table_data varchar2(40); --判斷表數據是否存在
--sql語句執行變量
execu_sql varchar2(2000);
begin
execu_sql := 'select count(*) from user';
execute immediate execu_sql into exit_table_data;
if exit_table_data=0 then
execu_sql := 'insert into user values('大明')';
execute immediate execu_sql;
commit;
end if;
end pro_test;
實例二:
create or replace procedure pro_test is
--邏輯判斷變量
exit_table_data varchar2(40); --判斷表數據是否存在
--sql語句執行變量
execu_sql varchar2(2000);
begin
execu_sql := 'select count(*) from user';
execute immediate execu_sql into exit_table_data;
if exit_table_data=0 then
execu_sql := 'insert into user values('大明')';
execute immediate execu_sql;
commit;
else
execu_sql:= 'update user set username='大華'';
execute immediate execu_sql;
commit;
end if;
end pro_test;
(2)、多if實例(if...then...elseif...then...else...end if;)
create or replace procedure proc_test (v_num in number)
as
begin
if v_num < 10
then
dbms_output.put_line (v_num);
elseif v_num > 10 and v_num < 50
then
dbms_output.put_line (v_num - 10);
else
dbms_output.put_line (v_num - 50);
end if;
end proc_test;
(2)、case ... when ... end case
實例一:
create or replace procedure proc_test (v_num in number)
as
begin
case v_num
when 1 then
dbms_output.put_line (v_num);
when 2 then
dbms_output.put_line (v_num);
when 3 then
dbms_output.put_line (v_num);
else null;
end case;
end proc_test;
6)、給變量賦值
我們在參數列表定義輸出參數、輸入輸出參數yi,以及在參數名位置定義參數,可能都需要一個賦值操作,讓查詢sql的結果賦值或者定義輸入參數賦值等等,那麼我們可以使用什麼方法給這些參數賦值呢?
下面列舉出一些常用的爲變量賦值的方法:
1、直接法
使用“ := ” 的符號爲變量賦值,例如: v_pare := "0";
2、select into
假如變量爲v_pare,那麼爲它賦值的語句爲:select count(*) into v_pare from user;
3、execute immediate 變量名(查詢sql語句結果賦值給它的變量)into 變量名
例如:
v_sqlfalg := 'select count(*) from user_tables where table_name='''||v_tablename || '''';
execute immediate v_sqlfalg into v_flag;
其中,v_tablename、v_sqlfalg、v_flag都是變量;
select into和execute immediate的區別:
1、execute immediate 賦值的變量是通過select語句查詢出來的,而select into是直接賦值給變量的。
7)、存儲過程跳出循環
oracle存儲過程可以使用3種方法跳出循環,分別是return、exit、continue;
它們的區別爲:
1、return是直接跳出存儲過程;
2、如果存在多層循環,exit是直接跳出存儲過程的本次循環,而去執行上一級循環的循環條件;
3、continue是本次循環後面的代碼部分不再執行,轉而執行本循環的下一次循環。
8)、Oracle存儲過程中是否需要寫commit的問題
是否需要在存儲過程中寫commit主要依據需求:
(1) 如果是不需要在存儲過程中進行提交,而是由調用程序負責提交或者回滾,那麼不需要在存儲過程中commit或者rollback。
(2) 如果不想由調用程序負責提交或者回滾,那麼就應該在存儲過程中進行commit或rollback;
另外,如果是純後臺數據庫開發,一定要寫.只是寫的時機同樣是分爲兩種,一種是寫在過程裏面;另一種是寫在調用存儲過程之後. 而之所以要寫commit的原因是,Oracle的默認事務級別是READ COMMITED;默認情況下,Oracle是不會自動提交的,需要手動提交才ok.
9)、使用plsql創建存儲過程步驟
1、登錄plsql後,在對象框中找到“Procedures”,點擊右鍵,找到新建,如圖所示:
2、進入到新建界面,如圖所示:
3、最終就進入到存儲過程結構中,你要做的就是編寫存儲過程邏輯。
10)、使用plsql對存儲過程進行調試
1、在“Procedures”下拉列表中找到已經編寫好的存儲過程,點擊右鍵,找到“測試”,如圖所示:
2、PL\SQL會打開調試界面,圖中位置1的按鈕就是開始調試的按鈕,在調試之前要填寫輸入參數的值,位置2就是填寫參數的地方,如果有多個參數,會有多行參數框,按參數名填寫相應的參數即可,如果沒有參數,可以不填。
3、填寫完參數,單擊開始調試按鈕後,調試的界面會發生一些變化。圖中位置1的變化,說明存過已經處於執行狀態,別人不能再編譯或者執行。位置2的按鈕就是執行按鈕,單擊這個按鈕存過會執行完成或者遇到bug跳出,否則是不會停下來的,調試時不會用這個按鈕的。位置3的按鈕纔是關鍵——單步執行,就是讓代碼一行一行的執行,位置4的按鈕是跳出單步執行,等待下一個指令。
今天的課程就講解到這裏,如果有不懂的地方,或者有建議,麻煩下方留言!