1. 程式人生 > >基於oracle數據庫存儲過程的創建及調用

基於oracle數據庫存儲過程的創建及調用

薪資 date 值類型 parameter 1.4 set集合 所有 cells plus

1、PLSQL編程

1.1概念和目的

PL/SQL(Procedure Language/SQL)

PLSQL是Oracle對sql語言的過程化擴展

指在SQL命令語言中增加了過程處理語句(如分支、循環),使SQL語言具有過程處理能力

1.2程序結構

通過PLsqlDeveloper工具的Test Windows創建程序模版或者通過語句在SQLWindows編寫

提示:PLSQL語言的大小是不區分的

PL/SQL可以分為三個部分:聲明部分、可執行部分、異常處理部分

[declare] --聲明變量,遊標(無變量聲明可以省略)

begin

--執行部分(方法)處理業務異常

end;

set serveroutput on --sqlplus 命令窗口

begin

DBMS_output.put_line(“Hello world”);

end;

/ ---需要在程序最後添加一個/標識程序的結束

1.3變量

聲明變量的方式

變量名 變量類型(變量長度) --v_name varchar2(20)

1.3.1普通變量(char varchar2 date number boolean long)

(1)直接賦值語句:= --v_name=’zhangsan’

(2)語句賦值,使用select…into…賦值(語法select值into變量)

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

declare
    v_name varchar2(20):=’zhangsan’;
    v_sal number;
    v_addr varchar2(200);
begin
    v_sal:=1580;
    select ‘ad’ into v_addr from dual;
    DBMS_output.put_line(‘姓名:’
|| v_name|| ’薪水:’ || v_sal ||‘地址:’||v_addr); end;

【示例】查詢 emp表中7839號員工的個人信息,打印姓名和薪水

declare
    v_name vachar2(20);
    v_sal number;
begin
    select ename,sal into v_name,v_sal from emp where empno=7839;
    DBMS_output.put_line(‘姓名:’|| v_name || ‘,薪水:’|| v_sal);
end;

1.3.2特殊變量類型(引用型變量、記錄型變量)

(1)引用型變量

【示例】查詢 emp表中7839號員工的個人信息,打印姓名和薪水

declare
    v_name emp.ename%TYPE;
    v_sal emp.sal%TYPE;
begin
    select ename,sal into v_name,v_sal from emp where empno=7839;
    DBMS_output.put_line(‘姓名:’|| v_name || ‘,薪水:’|| v_sal);
end;

使用普通變量定義方式,需要知道表中列的類型,而是用引用類型,不需要考慮列的類型,使用%TYPE是非常好的編程風格,因為它使得PL/SQL更加靈活,更加適應於對數據庫定義的更新。

(2)記錄型變量

接受表中的一行記錄,相當於Java中的一個對象

語法:變量名稱 表名%ROWTYPE

【示例】查詢 emp表中7839號員工的個人信息,打印姓名和薪水…..

declare
    v_emp emp%ROWTYPE;
begin
    select * into v_emp from emp where empno=7839;
    DBMS_output.put_line(‘姓名:’|| v_emp.ename || ‘,薪水:’|| v_emp.sal);
end;

如果有一個表,有100個字段,如果要使用這100字段名,如果使用引用型變量一個個聲明,會特別麻煩,記錄型變量可以方便的解決這個問題。

錯誤的使用:

1.記錄型變量只能存儲一個完整的行數據。

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

1.4流程控制

1.4.1條件分支

begin
    if 條件1 then 執行1
    elsif 條件2 then 執行2
    else 執行3
    end if;
end;

【示例】判斷emp表中記錄是否超過20條,10-20之間,或者10條以下

declare
    --聲明變量接受emp中的數量
    v_count number;
begin
    select count(1) into v_count from emp;
    if v_count>20 then DBMS_output.put_line(‘emp表中的記錄數超過了20條為:’|| v_count);
    elsif v_count>=10 then DBMS_output.put_line(‘emp表中的記錄數在10-20條為:’|| v_count);
    else DBMS_output.put_line(‘emp表中的記錄數10條以下為:’|| v_count);
    end if;
end;

1.4.2循環

在oracle中有三種循環方式,loop循環

語法:

begin
    loop
    exit when 退出循環條件
    end loop;
end;

【示例】打印數字1-10

declare
    v_num number:=1;
begin
    loop
    exit when v_num>10;
    dbms_output.put_line(v_num);
    v_num+=v_num+1;
    end loop;
end;

2、遊標

2.1什麽是遊標

用於臨時存儲一個查詢返回的多行數據(結構集,類似於Java的jdbc連接返回的ResultSet集合),通過遍歷遊標,可以逐行訪問處理該結果集的數據。

遊標的使用方式:聲明--à打開à讀取à關閉

2.2語法

遊標聲明:

cursor 遊標名[(參數列表)] is 查詢語句;

遊標的打開:

open 遊標名;

遊標的取值:

fetch 遊標名 into 變量列表;

遊標的關閉:

close 遊標名;

2.3遊標的屬性

遊標的屬性

返回值類型

說明

%ROWCOUNT

整型

獲得fetch語句返回的數據行數

%FOUND

布爾型

最近的fetch語句返回一行數據則為真,否則為假

%NOTFOUNT

布爾型

與%FOUND屬性返回值相反

%ISOPEN

布爾型

遊標已經打開時值為真,否則為假

其中%NOTFOUND是在遊標中找不到元素的時候返回TRUE,通常用來判斷退出循環

2.4創建和使用

無參遊標

【示例】使用遊標查詢emp表中所有員工的姓名和工資,並將其依次打印出來。

declare
--聲明遊標
    cursor c_emp is select ename,sal from emp;
--聲明變量用來接受遊標中的元素
    v_ename emp.ename%type;
    v_sal emp.sal%type;
begin
--打開遊標
    open c_emp;
遍歷遊標
    loop
    
--獲取遊標中的數據
    fetch c_emp into v_ename,v_sal;
--退出循壞條件
    exit when c_emp%notfound;
    dbms_output.put_line(‘姓名:’||v_name||’,薪水:’||v_sal);
    end loop;
--關閉遊標
    close c_emp;
end;

帶參遊標

【示例】使用遊標查詢並打印某部門的員工的姓名和薪資,部門編號為運行時手動輸入。

declare
--聲明遊標
    cursor c_emp(v_deptno emp.deptno%type) is 
    select ename,sal from emp where deptno=v_deptno;
--聲明變量用來接受遊標中的元素
    v_ename emp.ename%type;
    v_sal emp.sal%type;
begin
--打開遊標
    open c_emp;
遍歷遊標
    loop
--獲取遊標中的數據
    fetch c_emp into v_ename,v_sal;
--退出循壞條件
    exit when c_emp%notfound;
    dbms_output.put_line(v_name || v_sal);
    end loop;
--關閉遊標
    close c_emp;
end;

3、存儲過程

3.1概念作用

之前我們編寫的PLSQL語句程序可以進行表的操作,判斷,循環邏輯處理的工作,但無法重復調用。可以理解之前的代碼全部編寫在了main方法中,是匿名程序。Java可以通過封裝對象和方法來解決復用問題,PLSQL是將一個個PLSQL的業務處理過程存儲起來進行復用,這些被存儲起來的PLSQL程序稱之為存儲過程。

存儲過程作用:

  1. 在開發過程中,為了一個特定的業務功能,會向數據庫進行多次連接關閉(連接和關閉是很耗費資源),需要對數據庫進行多次I/O讀寫,性能比較低。如果把這些業務放到PLSQL中,在應用程序中只需要調用PPLSQL就可以做到連接關閉一次數據庫就可以實現我們的業務,可以大大提高效率。
  2. ORACLE官方給的建議:能夠讓數據庫操作的不要放在程序中。在數據庫中實現基本上不會出現錯誤,在程序中操作可能會存在錯誤。(如果在數據庫中操作數據,可以有一定的日誌恢復等功能)

3.2語法

create or replace procedure 過程名稱[(參數列表)] is
begin

end [過程名稱];

根據參數的類型,我們將其分為3類講解:

不帶參數的

帶輸入參數的

帶輸入輸出參數(返回值)的

3.3無參存儲

3.3.1創建存儲

3.3.2調用存儲

create or replace procedure p_hello as
begin
    dbms_output.put_line(‘hello word’);
end p_hello;

begin
p_hello;
end;

exec p_hello; -----sqlplus

註:is和as是可以會用的,用哪個都沒有關系;過程中沒有declare關鍵字,declare用在語句塊中

3.4帶輸入參數的存儲過程

【示例】查詢並打印某個員工(如7839號員工)的姓名和薪水—存儲過程:要求:調用的時候傳入員工編號,自動控制臺打印。

create or replace procedure p_querynameandsal(v_empno in emp.empno%type) is
--聲明變量接受查詢結果
    v_name emp.ename%type;
    v_sal emp.sal%type;
begin
--查詢emp表中某個員工的姓名和薪水並賦值給變量
    select ename,sal into v_name,v_sal from emp where empno=v_empno;
    dbms_output.put_line(v_name || v_sal);
end;
declare
    i integer;
begin
    p_querynameandsal(7839);
end

exec p_querynameandsal(7839);

3.5帶輸出參數的存儲過程

【示例】輸入員工號查詢某個員工(7839號員工)信息,要求,將薪水作為返回值輸出,給調用的程序使用。

create or replace procedure p_querysal_out(v_empno in emp.empno%type,o_sal out emp.sal%type) as
begin
    select sal into o_sal from emp where empno=v_empno;
end;
declare
    v_sal emp.sal%type;
begin
    p_querysal_out(7839,v_sal);
    dbms_output.put_line(v_sal);
end

3.6JAVA程序調用存儲過程

需求:如果一條語句無法實現結構集,比如需要多表查詢,或者需要復雜邏輯查詢,我們可以選擇調用存儲出你的結果。

結論:通過 Connection對象的prepareCall方法傳遞一個轉義SQL語句可以實現調用存儲過程。輸入參數直接調用set方法傳遞,輸出參數需要註冊後,執行存儲過程,通過get方法獲取,參數列表的下標是從1開始的。

public interface CallableStatement

  • extends PreparedStatement

用於執行SQL存儲過程的界面。 JDBC API提供了存儲過程SQL轉義語法,允許以標準方式為所有RDBMS調用存儲過程。 此轉義語法包含一個結果參數和不包含結果參數的表單。 如果使用,結果參數必須註冊為OUT參數。 其他參數可用於輸入,輸出或兩者。 參數按順序依次引用,第一個參數為1。

{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}

{call <procedure-name>[(<arg1>,<arg2>, ...)]}

IN參數值使用從PreparedStatement繼承的set方法設置。 所有OUT參數的類型必須在執行存儲過程之前進行註冊; 它們的值通過這裏提供的get方法在執行get 。

import oracle.jdbc.OracleTypes;
import java.sql.CallableStatement;
import java.sql.DriverManager;
import java.sql.Connection;
public class JdbcTest{
    public static void main(String[] args){
        //1.加載驅動
        Class.forName(“oracle.jdbc.driver.PracleDriver”);
        //2.獲取連接
        String url=”jdbc:oracle:thin:@localhost:1521:xe”;
        String name=”scott”;
        String password=”tigger”;
        Connection conn=DriverManager.getConnection(url,name,password);
        //3.獲取語句對象
        String sql=”{call p_querysal_out(?,?)}”;
        CallableStatement call=conn.prepareCall(sql);
        //4.設置輸出參數
        call.setInt(1,7839);
        //5.註冊輸出參數
        call.registerOutParameter(2,OracleTypes.DOUBLE);
        //6.執行存儲過程
        call.execute();
        //7.獲取輸出參數
        double sal=call.getDouble(2);
        System.out.println(“薪水:”+sal);
        //8.釋放資源
        call.close();
        conn.close();
    }
}

視頻整理:https://www.bilibili.com/video/av46777605

基於oracle數據庫存儲過程的創建及調用