oracle存儲過程相關整理


存儲過程:

存儲過程是 SQL, PL/SQL, Java 語句的組合, 它使你能將執行商業規則的代碼從你的應用程序中移動到數據庫。這樣的結果就是,代碼存儲一次但是能夠被多個程序使用。是存放在數據庫服務器上的SQL語句塊,其效率高於同等SQL語句6-10倍

下面通過例子讓你了解存儲過程對數據的增刪查改(對Oracle中的emp操作)

一、Oracle存儲過程語法:

Create [or replace] procedure 存儲過程名稱 (輸入參數或輸出參數)]as

變量

Begin

執行主體

End;

二、IN, OUT , IN OUT 用來修飾參數。

IN 表示這個變量必須被調用者賦值然后傳入到 PROCEDURE 進行處理。

OUT 表示 PRCEDURE 通過這個變量將值傳回給調用者。

IN OUT 則是這兩種的組合。

三、執行存儲過程方式:

1、Call 存儲過程名稱(參數);

2、Execute 存儲過程名稱(參數);

注意:在oracle 數據庫中,call命令任何窗口都能使用,但是execute只能在命令窗口使用,否則會報無效的SQL語句的異常。

四、在存儲過程中需要注意事項:

1、在oracle數據庫存儲過程中,表別名不能用as

2、在oracle數據庫存儲過程中,select某一字段時,后面必須緊跟into,如果select整個記錄則必須使用游標處理

3、在使用select....into....時必須保證數據庫有該數據,否則報”no data found”異常

4、在存儲過程中,別名不能和字段名相同,否則雖然編譯能通過,但是運行結果會報錯

五、存儲過程基本語法

--案例一:無參存儲過程
--1.創建結構
CREATE PROCEDURE procedureName--存儲過程名字
  AS                          --as可替換成 is
    --聲明變量
  BEGIN
    --執行主體
END;

--2.案例
create or replace procedure firstPro is
begin
  dbms_output.put_line('Hello World');--打印輸出
exception   --存儲過程異常
  WHEN OTHERS THEN
    ROLLBACK;
end firstPro;

--3.數據庫調用存儲過程:執行結果:output:  Hello World
--(21) begin-end
begin
  firstPro();
end;
--(22)call
call firstPro();

--4.刪除存儲過程
drop procedure firstPro;
--案例二:帶參存儲過程(in:入參)
--1.案例
create or replace procedure secondPro(num in number) as
begin
  dbms_output.put_line('The input num is :'||num);
end;
--2.調用
--(21)
call secondPro(4);
--(22)
begin
  secondPro(7);
end;
--(23)
declare
  n number;
begin
  n := 1;
  secondPro(num=>n);
end;
--or
Begin
  secondPro(num=>1);
end;
--備注:=> 是 Oracle 中調用 存儲過程的時候, 指定 參數名進行調用
--一般如果是按順序填寫參數的時候,是不需要用=>符號的,
--但是Oracle可以讓你在調用的時候,指定"參數名稱=>參數值", 這樣就可以不按參數的順序進行調用.
-- => 前面的變量為存儲過程的“形參”且必須於存儲過程中定義的一致,而=>后的參數為“實際參數”。
--案例三:存儲過程:聲明變量
--1.案例
CREATE OR REPLACE procedure thirdPro
  is
    n_start   number;
    n_end   number;
    count_num number;
    use_time number;
  begin
    n_start:=dbms_utility.get_time;
    dbms_output.put_line('This   statement   start  time : '|| n_start );
    --查看oracle數據庫版本
    SELECT count(*) into count_num FROM v$version;
    n_end:=dbms_utility.get_time;
    dbms_output.put_line('This   statement   end  time : '|| n_end );
    use_time:=   n_end   -   n_start;
    dbms_output.put_line('This   statement   cost   '|| use_time ||'   miliseconds');
end;
--備注:
--(1)dbms_utility.get_time 返回當前時間的1/100秒,毫秒
--它是用以前后兩個取點做對s比的,單個是沒有具體意義的,就是用來取差值的!

--2.執行存儲過程
--(21)
call thirdPro();
--(22)
begin
   thirdPro();
end;
--案例四:動態sql語句執行
--1.案例
CREATE OR REPLACE PROCEDURE FourthProc(id varchar2 ,dicName VARCHAR2) AS
mysql VARCHAR2(500);
BEGIN
  mysql:='UPDATE sys_dictionary SET dic_name=:1 WHERE id=:2';
  EXECUTE IMMEDIATE mysql USING dicName,id;
  commit;
END;

--2.執行存儲過程
CALL FourthProc('22ff8102-95cd-4862-a2ec-d011eca75ef1','')
--案例五:返回結果集
--1.案例
create or replace procedure FifthPro(
       cur_OUT    OUT    SYS_REFCURSOR
) is

begin
   OPEN cur_OUT FOR
      select cname,merch_no,taxno zjid,'營業執照' zjname,BUSINESS_LICENSE_VALIDITY validity,trunc(BUSINESS_LICENSE_VALIDITY-sysdate) gqdate from quas.base_merchant
      where  BUSINESS_LICENSE_VALIDITY-sysdate < 60 ;

end FifthPro;

2.案例五:Test測試存儲過程步驟:Test-》點擊Start Debugger 按鈕:開始執行存儲過程-》點擊run按鈕存儲過程直接執行到結束,返回如圖2的結果Cursor->點擊右上角的按鈕,查看結果集:如圖3所示。(若點擊step  into 按鈕,則進入存儲過程詳細代碼,按步執行)

3.java代碼執行存儲過程:

/**
 *
 */
package kklazy.reportquery.service;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.hibernate.Session;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import kklazy.ctps.service.DefaultCtpsService;
import kklazy.reportquery.model.ReportQueryEntity;
import oracle.jdbc.internal.OracleTypes;

/**
 * @author Administrator
 *
 */
@Service("fifthProService")
@Transactional(rollbackOn=Exception.class)
public class FifthProService extends DefaultCtpsService<ReportQueryEntity, String>{
    //注入jdbc連接參數
    @Value("${ctps.database.driver}")
    private String driverClass;
    @Value("${ctps.database.url}")
    private String url;
    @Value("${ctps.database.username}")
    private String username;
    @Value("${ctps.database.password}")
    private String password;


    /**
     * 執行存儲過程
     */
    public List<ReportQueryEntity> execute() {
        Session session = (Session) this.getJpa().getManager().getDelegate();
        SessionFactoryImpl sessionFactory = (SessionFactoryImpl) session.getSessionFactory();
        Connection conn = null;
        ResultSet  result = null;
        List<ReportQueryEntity> allList = new ArrayList<ReportQueryEntity>();
        try {
            conn = sessionFactory.getConnectionProvider().getConnection();
            if (conn == null || conn.isClosed()) {
                try {
                    Class.forName(driverClass);
                    conn = DriverManager.getConnection(url, username, password);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            CallableStatement call = conn.prepareCall("{call  FifthPro(?,?)}");
            System.out.println();
            call.setString(1, "00");
            call.registerOutParameter(2, OracleTypes.CURSOR);
            call.execute();
            result = (ResultSet)call.getObject(2);
            if(result == null) {
                System.out.println("查詢失敗!");
            }else {
                allList = getFindList(result);
                System.out.println("查詢成功");
            }
            System.out.println("執行存儲過程的結果是:" + result);
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println(e);
        }finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return allList;
    }

    public List<ReportQueryEntity> getFindList(ResultSet result) throws SQLException{

        List<ReportQueryEntity> allList = new ArrayList<ReportQueryEntity>();
        if(null !=result ) {
            while (result.next()) {
                ReportQueryEntity reportEntity = new ReportQueryEntity();
                reportEntity.setData1(result.getString(1));
                reportEntity.setData2(result.getString(2));
                reportEntity.setData3(result.getString(3));
                reportEntity.setData4(result.getString(4));
                reportEntity.setData5(result.getString(5));
                reportEntity.setData6(result.getString(6));

                allList.add(reportEntity);
            }
        }
        return allList;
    }

}

案例六、查詢所有數據(游標的具體使用詳見:https://www.cnblogs.com/xiaoliu66007/p/7495753.html)

PL/SQL 中 SELECT 語句只返回一行數據。如果超過一行數據,那么就要使用顯式游標,INTO 子句中要有 SELECT子句中相同列數量的變量。

INTO 子句中也可以是記錄變量。

--案例六:顯式游標
--------1.用游標顯示查詢所有的結果
CREATE OR REPLACE procedure sys_dictionary_proc
AS
CURSOR dictionary_emp IS SELECT * FROM sys_dictionary where dic_group ='OPERATE_TYPE';--定義游標,該游標指向查詢結果
rowresult sys_dictionary%ROWTYPE;
BEGIN
  OPEN dictionary_emp;--打開游標
  LOOP FETCH dictionary_emp INTO rowresult;--將游標中的值賦給rowresult
    EXIT WHEN dictionary_emp%NOTFOUND;--判斷:游標不存在時跳出循環
    dbms_output.put_line('分組:'||rowresult.dic_group||'值:'||rowresult.DIC_VALUE||'顯示名:'||rowresult.dic_name);
  END LOOP;
  CLOSE dictionary_emp;--關閉游標
END;
drop procedure sys_dictionary_proc;

--2.調用
CALL sys_dictionary_proc();

3.output結果:

分組:OPERATE_TYPE值:1顯示名:新增
分組:OPERATE_TYPE值:2顯示名:修改
分組:OPERATE_TYPE值:3顯示名:刪除


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM