ORACLE存儲(chǔ)過程學(xué)習(xí)

1.1、輸出helloworld

SQL> set serveroutput on
SQL> BEGIN
  2  DBMS_OUTPUT.put_line('HELLO');
  3  END;
  4  /

注意點(diǎn):執(zhí)行結(jié)束后并未顯示輸出的結(jié)果,默認(rèn)情況下,輸出的選項(xiàng)是關(guān)閉狀態(tài)的,我們需要開啟一下 set serveroutput on

image.png

1.2變量

PLSQL編程中常見的變量分兩大類:

1.普通數(shù)據(jù)類型(char,varchar2, date, number, boolean, long)

2.特殊量類型(引用型委量、記錄型交量)

聲明變量的方式為

1變量名變量類型(變量長度)       例如:v_name varchar2(202月

1.41普通變量

變量賦值的方式有兩種:

1.直接賦值語句 := eg: v_name :='zhang'

2.語句賦值,使用select ...into ...賦值: (語法select值tinto變量)

【示例】打印人員個(gè)人信息,包括:姓名、薪水、地址

--打印人員個(gè)人信息,包括:姓名、薪水、地址
DECLARE
--姓名
V_NAME VARCHAR2(20):='張三'; --聲明變量直接賦值--薪水
v_SAL NUMBER;--地址
V_ADDR VARCHAR2 (200);

BEGIN
--在程序中直接賦值
v_SAL :=1580;

--語句賦值
SELECT '昆明'INTO V_ADDR FROM DUAL;

--打印變量
DBMS_OUTPUT.PUT_LINE('姓名:'||V_NAME ||',薪水:'|| v_SAL ||',地址:'||V_ADDR);
END;
image.png
image.png

1.4.2.引用型變量

變量的類型的長度取決于表中字段的類型和長度

通過表名.列名%TYPE指定變量的類型和長度,例如: v_name emp.ename%TYPE;

【示例】查詢emp表中7839號(hào)員工的個(gè)人信息,打印姓名和薪水

--查詢emp表中7839號(hào)員工的個(gè)人信息,打印姓名和薪水
DECLARE
--姓名
V_NAME emp.ename%TYPE;--薪水
V_SAL emp.sal%TYPE;
BEGIN
SELECT ENAME,SAL INTO V_NAME,V_SAL FROM EMP WHERE pid = 1;--打印輸出
DBMS_OUTPUT.PUT_LINE('姓名:'|| V_NAME|| ',薪水:'|| V_SAL);
END;
image.png
image.png

引用型變量的好處:
使用普通變量定義方式,需要知道表中列的類型,而使朋用類型,不需要考慮列的類型,使用%TYPE是非常好的編程風(fēng)格,因?yàn)樗沟肞LSQL更加靈活,更加適應(yīng)于對(duì)數(shù)據(jù)庫定義的更新。

1.4.3.記錄型變量

接受表中的一整行記錄,相當(dāng)于Java中的一個(gè)對(duì)象
語法:變量名稱表名%ROWTYPE,例如: v_emp emp%rowtype;

--查詢emp表中7839號(hào)員工的個(gè)人信息,打印姓名和薪水
DECLARE
--姓名
V_EMP emp%ROWTYPE;--
BEGIN
SELECT * INTO V_EMP FROM EMP WHERE pid = 1;--打印輸出
DBMS_OUTPUT.PUT_LINE('姓名:'|| V_EMP.ename|| ',薪水:'||V_EMP.SAL);
END;

如果有一個(gè)表,有100個(gè)字段,那么你程序如果要使用這100字段話,如果你使用型變量一個(gè)個(gè)聲明,會(huì)特別麻煩,記錄型變量可以方便的解決這個(gè)問題
錯(cuò)誤的使用:
1.記錄型變量只能存儲(chǔ)個(gè)完整的行數(shù)據(jù)


image.png

2.返回的行太多了,記錄型變量也接收不了


image.png

1.5流程控制
1.5.1.條件分支
語法:

BEGIN
IF 條件1 THEN 執(zhí)行1
ELSIF 條件2 THEN 執(zhí)行2
ELSE 執(zhí)行3
END IF;
END;

--判斷emp表中數(shù)據(jù)的條數(shù)
DECLARE
-- 聲明變量 接收emp表中的記錄數(shù)
v_count number;
BEGIN
--查詢emp表中的記錄賦值給變量
SELECT count(1) INTO v_count FROM EMP;
--判斷打印
  IF v_count > 20 THEN
    DBMS_OUTPUT.PUT_LINE('EMP表的中數(shù)據(jù)大于了20條,條數(shù)為' || v_count);
  ELSIF v_count >= 10 then
    DBMS_OUTPUT.PUT_LINE('EMP表的中數(shù)據(jù)介于10-20之間,條數(shù)為' || v_count);
  else
    DBMS_OUTPUT.PUT_LINE('EMP表的中數(shù)據(jù)小于10條,條數(shù)為' || v_count);
  end if;
END;

1.5.2.循環(huán)

在ORACLE中有三種循環(huán)方式,這里我們不展開,只介紹其中一種: loop循環(huán)
語法:

BEGIN
 LOOP
  EXIT WHEN   退出循環(huán)條件
 END LOOP;
END;

--打印數(shù)字1-10

DECLARE
  --聲明循環(huán)變量并賦值
  v_num number :=1;
BEGIN
   loop
     exit when v_num>10;
     DBMS_OUTPUT.put_line(V_NUM);
--循環(huán)變量自增
     V_NUM:=V_NUM+1;
     END LOOP;
END;

2.游標(biāo)

2.1.什么是游標(biāo)

用于臨時(shí)存儲(chǔ)一個(gè)查詢返回的多行數(shù)據(jù)(結(jié)果集,類似于Java的Jdbc連接返回的ResultSet集合),通過遍歷游標(biāo),可以逐行訪問處理該結(jié)果集的數(shù)據(jù)。
游標(biāo)的使用方式:聲明--->打開--->讀取--->關(guān)閉

2.2.語法

游標(biāo)聲明:
CURSOR游標(biāo)名[(參數(shù)列表)]IS查詢語句
游標(biāo)的打開:
OPEN 游標(biāo)名;
游標(biāo)的取值:
FETCH游標(biāo)名INTO變量列表;
游標(biāo)的關(guān)閉:
CLOSE游標(biāo)名;
2.3.游標(biāo)的屬性

游標(biāo)的屬性 返回值類型 說明
%ROWcOUNT 整型 獲得FETCH語句返回的數(shù)據(jù)行數(shù)
%FOUND 布爾型 最近的FETCH語句返回一行數(shù)據(jù)則為真,否則為假
%NOTFOUND 布爾型 與%FOUND屬性返回值相反
%ISOPEN 布爾型 游標(biāo)已經(jīng)打開時(shí)值為真,否則為假

其中%NOTFOUND是在游標(biāo)中找不到元素的時(shí)候返回TRUE,通常用來判斷退出循環(huán)
2.4創(chuàng)建和使用
【示例】使用游標(biāo)查詢emp表中所有員工的姓名和工資,并將其依次打印出來

--使用游標(biāo)查詢emp表中所有員工的姓名和工資,并將其一次打印出來 
DECLARE
  --定義游標(biāo)
  CURSOR C_EMP IS SELECT ename,sal FROM EMP;
  
  --聲明變量用來接收游標(biāo)的數(shù)據(jù)
  V_NAME EMP.ENAME%TYPE;
  V_SAL  EMP.SAL%TYPE;
  
BEGIN
  --打開游標(biāo)
  OPEN C_EMP;
     LOOP
       --通過 FETCH 語句獲取游標(biāo)中的值并賦給變量
       FETCH C_EMP INTO V_NAME,V_SAL;
       EXIT WHEN C_EMP%NOTFOUND;
       DBMS_OUTPUT.put_line('姓名:'||v_name||',工資:'||v_sal);
       end LOOP;
  --關(guān)閉游標(biāo)
  CLOSE C_EMP;
END;

image.png

image.png

2.5.帶參數(shù)的游標(biāo)
【示例】使用游標(biāo)查詢emp表中id為1的員工信息,編號(hào)為運(yùn)行時(shí)手動(dòng)輸入。

--使用游標(biāo)查詢emp表中id為1的員工信息
DECLARE
--定義游標(biāo)
CURSOR C_EMP(v_pid  emp.pid%TYPE) IS SELECT ename,sal FROM EMP WHERE PID=V_PID;

--聲明變量用來接收游標(biāo)的數(shù)據(jù)
V_NAME EMP.ENAME%TYPE;
V_SAL  EMP.SAL%TYPE;

BEGIN
--打開游標(biāo)
OPEN C_EMP(1);
  LOOP
    --通過 FETCH 語句獲取游標(biāo)中的值并賦給變量
    FETCH C_EMP INTO V_NAME,V_SAL;
    EXIT WHEN C_EMP%NOTFOUND;
    DBMS_OUTPUT.put_line('姓名:'||v_name||',工資:'||v_sal);
    end LOOP;
--關(guān)閉游標(biāo)
CLOSE C_EMP;
END;

注意:%NOTFOUND屬性默認(rèn)值為FLASE,所以在循環(huán)中要注意判斷條件的位.如果先判斷在FETCH會(huì)導(dǎo)致最后一條記錄的值被打印兩次(多循環(huán)一次默認(rèn));

3.存儲(chǔ)過程

3.1.概念作用
之前我們編寫的PLSQL程序可以進(jìn)行表的操作,判斷,循環(huán)邏輯處理的工作,但無法重復(fù)調(diào)用.
可以理解之前的代碼全都編寫在了main方法中,是匿名程序. JAVA可以通過封裝對(duì)象和方法來解決復(fù)用問題
PLSQL是將一個(gè)個(gè)PLSQL的業(yè)務(wù)處理過程存儲(chǔ)起來進(jìn)行復(fù)用,這些被存儲(chǔ)起來的PLSQL程序稱之為存儲(chǔ)過程

存儲(chǔ)過程作用:
1,在開發(fā)程序中,為了一個(gè)特定的業(yè)務(wù)功能,會(huì)向數(shù)據(jù)庫進(jìn)行多次連接關(guān)閉(連接和關(guān)閉是很耗費(fèi)資源)需要對(duì)數(shù)據(jù)庫進(jìn)行多次IO讀寫,性能比較低。如果把這些業(yè)務(wù)放到PLSQL中,在應(yīng)用程序中只需要調(diào)用PLSQL就可以做到連接關(guān)閉一次數(shù)據(jù)庫就可以實(shí)現(xiàn)我們的業(yè)務(wù),可以大大提高效率.

2,ORACLE官方給的建議:能夠讓數(shù)據(jù)庫操作的不要放在程序中。在數(shù)據(jù)庫中實(shí)現(xiàn)基本上不會(huì)出現(xiàn)錯(cuò)誤,在程序中操作可能會(huì)存在錯(cuò)誤.(如果在數(shù)據(jù)庫中操作數(shù)據(jù),可以有一定的日志恢復(fù)等功能.)

3.2.語法

 CREATE OR REPLACE PROCEDURE 過程名稱[(參數(shù)列表)] IS 
BEGIN

END[過程名稱];

根據(jù)參數(shù)的類型,我們將其分為3類講解:
不帶參數(shù)的
帶輸入?yún)?shù)的
帶輸入輸出參數(shù)(返回值)的。

3-3.無參存儲(chǔ)

3.3.1.創(chuàng)建存儲(chǔ)

通過Plsql Developer或者語句創(chuàng)建存儲(chǔ)過程:
新建一個(gè)Procedure

create or replace procedure P_HELLO  is
begin
    DBMS_OUTPUT.put_line('你妹的...');
end P_HELLO;
image.png

2、調(diào)用存儲(chǔ)過程

begin
--直接輸入存儲(chǔ)過程的名稱
  p_hello; 
  p_hello;
  p_hello;
  p_hello;
end ;
image.png

sql 窗口執(zhí)行

set serveroutput on 
create or replace procedure P_HELLO  is
begin
    DBMS_OUTPUT.put_line('你妹的...');
end P_HELLO;
--命苦窗口 通過exec 調(diào)用
exec p_hello  //輸出

image.png

注意:
第一個(gè)問題:is和as是可以互用的,用哪個(gè)都沒關(guān)系的
第二個(gè)問題:過程中沒有declare關(guān)鍵字,declare用在語句塊中

3.4帶參數(shù)的存儲(chǔ)過程

--帶參數(shù)的存儲(chǔ)過程
create or replace procedure query_emp(i_empno in emp.pid%type)  is
--聲明變量
v_name emp.ename%type;
v_sal  emp.sal%type;

begin
  select ename,sal into v_name,v_sal from emp where pid=i_empno;
  
    DBMS_OUTPUT.put_line('姓名:'||v_name||',薪資:'||v_sal);
end ;

運(yùn)行

begin
 query_emp(1);
end ;

image.png

sqlplus運(yùn)行

exec query_emp(1)
image.png

3.5帶輸出參數(shù)的存儲(chǔ)過程

--帶輸入輸出參數(shù)的存儲(chǔ)過程
create or replace procedure query_emp_out(i_empno in emp.pid%type,  o_sal out emp.sal%type)  is

begin
  select sal into o_sal from emp where pid=i_empno;
end ;

運(yùn)行

declare
v_sal emp.sal%type;
begin
  query_emp_out(1,v_sal);  
  DBMS_OUTPUT.put_line(V_SAL);
end;

java調(diào)用存儲(chǔ)過程

public static void main(String] args) throws Exception {
//1.加載驅(qū)動(dòng)
Class.forName("oracle.jdbc.driver. OracleDriver") ;
//2.獲取連接對(duì)象
String url = "jdbc:oracle:thin:Clocalhost:1521:xe";string user ="scott";
String password = "tiger";
Connection conn = DriverManager. getConnection(url,user,password);
//3.獲取語句對(duì)象
string sql = "{call p_querysal_out(?,?)}";//轉(zhuǎn)義語法, {call存儲(chǔ)過程(參數(shù)列表)}
Callablestatement call = conn.preparecall(sql);
1/4.設(shè)置輸入?yún)?shù)
call.setInt(1,7839);
//5.注冊(cè)輸出參數(shù)
call.registeroutParameter(2,oracleTypes.DOUBLE);
//6.執(zhí)行存儲(chǔ)過程
call.execute();
1/7.獲取輸出參數(shù)
double sal = call.getDouble(2);system.out.println("薪水:"+sal);
1/8.釋放資源
call.close();
conn.close();
 }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容