前言~
今天莫名的接到一個任務,須要使用oracle定時任務和oracle存儲過程來每日建立一個日誌表,因爲小編呢還沒有接觸過存儲過程和定時任務,因此今天學習了一番,特定來總結一下。望能給予一些未接觸過存儲過程的小夥伴一些幫助。sql
今入今天的正題,首先要了解一下oracle的存儲過程,都有哪些結構,而plsql是一個輔助工具,是能幫助咱們更輕鬆的實現存儲過程。數據庫
上述就是一個無參的存儲過程實例,一個存儲過程大致分爲這麼幾個部分:oracle
1)、建立語句:create or replace procedure 存儲過程名稱 [authid current_user] ;工具
「」[]「」中括號的內容是可選的,其表示修改存儲過程,加入authid current_user時存儲過程可使用role權限。不然會報ORA-01031權限不足。oop
若是沒有or replace語句,那只是新建一個存儲過程,若是系統中存在相同的存儲過程,則會報錯,Create or replace procedure 若是系統中沒有此存儲過程就新建一個,若是系統中有此存儲過程則把原來刪除掉,從新建立一個存儲過程。學習
存儲過程名定義:包括存儲過程名和參數列表、參數名和參數類型。參數列表可不寫,如例子所示。參數名不能重複,而且每一個參數之間用分號「 ;」 隔開, 參數傳遞方式:IN, OUT, IN OUT。以下面例子所示:測試
下面說明一下參數傳遞方式:spa
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 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的結果賦值或者定義輸入參數賦值等等,那麼咱們可使用什麼方法給這些參數賦值呢?
下面列舉出一些經常使用的爲變量賦值的方法:
一、直接法
使用「 := 」 的符號爲變量賦值,例如: v_pare := "0";
二、select into
假如變量爲v_pare,那麼爲它賦值的語句爲:select count(*) into v_pare from user;
三、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的區別:
一、execute immediate 賦值的變量是經過select語句查詢出來的,而select into是直接賦值給變量的。
7)、存儲過程跳出循環
oracle存儲過程可使用3種方法跳出循環,分別是return、exit、continue;
它們的區別爲:
一、return是直接跳出存儲過程;
二、若是存在多層循環,exit是直接跳出存儲過程的本次循環,而去執行上一級循環的循環條件;
三、continue是本次循環後面的代碼部分再也不執行,轉而執行本循環的下一次循環。
8)、Oracle存儲過程當中是否須要寫commit的問題
是否須要在存儲過程當中寫commit主要依據需求:
(1) 若是是不須要在存儲過程當中進行提交,而是由調用程序負責提交或者回滾,那麼不須要在存儲過程當中commit或者rollback。
(2) 若是不想由調用程序負責提交或者回滾,那麼就應該在存儲過程當中進行commit或rollback;
另外,若是是純後臺數據庫開發,必定要寫.只是寫的時機一樣是分爲兩種,一種是寫在過程裏面;另外一種是寫在調用存儲過程以後. 而之因此要寫commit的緣由是,Oracle的默認事務級別是READ COMMITED;默認狀況下,Oracle是不會自動提交的,須要手動提交才ok.
9)、使用plsql建立存儲過程步驟
一、登陸plsql後,在對象框中找到「Procedures」,點擊右鍵,找到新建,如圖所示:
二、進入到新建界面,如圖所示:
三、最終就進入到存儲過程結構中,你要作的就是編寫存儲過程邏輯。
10)、使用plsql對存儲過程進行調試
一、在「Procedures」下拉列表中找到已經編寫好的存儲過程,點擊右鍵,找到「測試」,如圖所示:
二、PL\SQL會打開調試界面,圖中位置1的按鈕就是開始調試的按鈕,在調試以前要填寫輸入參數的值,位置2就是填寫參數的地方,若是有多個參數,會有多行參數框,按參數名填寫相應的參數便可,若是沒有參數,能夠不填。
三、填寫完參數,單擊開始調試按鈕後,調試的界面會發生一些變化。圖中位置1的變化,說明存過已經處於執行狀態,別人不能再編譯或者執行。位置2的按鈕就是執行按鈕,單擊這個按鈕存過會執行完成或者遇到bug跳出,不然是不會停下來的,調試時不會用這個按鈕的。位置3的按鈕纔是關鍵——單步執行,就是讓代碼一行一行的執行,位置4的按鈕是跳出單步執行,等待下一個指令。
今天的課程就講解到這裏,若是有不懂的地方,或者有建議,麻煩下方留言!