程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle中的子程序之一存儲過程

Oracle中的子程序之一存儲過程

編輯:Oracle數據庫基礎

子程序就是能夠接受參數並被其他程序所調用的命名PL/SQL塊。PL/SQL子程序有兩種類型,過程和函 數。通俗地講,過程用於執行一個操作,而函數用於返回一個結果值。同匿名PL/SQL塊類似,子程序也 有聲明部分,執行部分和一個可選的異常處理部分,聲明部分包含類型、游標、常量、變量、異常和嵌 套子程序的聲明。這些內容都針對當前的子程序有效,也就是說在子程序退出時聲明的這些內容會自動 失效。執行部分包含賦值語句、流程控制語句和Oracle的數據操作語句。異常處理部分包含異常處理程 序。

一、過程 (存儲過程)

過程是一個能執行某個特定操作的子程序。使用CREATE OR REPLACE創建或者替換保存在數據庫中的一個子程序。

示例1:聲明存儲過程,該過程返回dept表 行數

DECLARE
PROCEDURE getDeptCount
AS
deptCount INT;
BEGIN
SELECT COUNT(*) INTO deptCount FROM DEPT;
DBMS_OUTPUT.PUT_LINE('DEPT 表的共有記錄數:'||deptCount);
END getDeptCount;
BEGIN
getDeptCount [()];
END;

注意:此存儲過程getDeptCount只在塊運行時有效。

示例2:創 建不帶參數的存儲過程,該過程返回dept表行數

CREATE OR REPLACE PROCEDURE getDeptCount
AS | IS
deptCount int;
BEGIN
SELECT COUNT(*) INTO deptCount FROM dept;
DBMS_OUTPUT.PUT_LINE('dept表共有'||deptCount||'行記錄 ');
END [getDeptCount];

當我們創建的存儲過程沒有參數時,在存儲過程名 字後面不能有括號。在AS或者IS後至BEGIN之前是聲明部分,存儲過程中的聲明不使用DECLARE關鍵字。 同匿名PL/SQL塊一樣,EXCEPTION和聲明部分都是可選的。

當我們創建的過程帶有錯誤時,我們 可以通過SELECT * FROM USER_ERRORS查看,或者使用SHOW ERRORS [ PROCEDURE Proc_Name]查看。

使用以下代碼可以執行存儲過程:

BEGIN
getDeptCount;
END;

以上存儲過程還可以通過以下代碼來簡化調用:

EXEC getDeptCount[;]   
CALL  getDeptCount();

注意:

並不是所有的存 儲過程都可以用這種方式來調用

定義無參存儲過程時,存儲過程名後不能加()

在塊中或 是通過EXEC調用存儲過程時可以省略()

通過CALL調用無參存儲過程必須加上()

示例3:創 建帶有輸入參數的存儲過程,該過程通過員工編號打印工資額

CREATE OR REPLACE PROCEDURE getSalaryByEmpNo(eNo NUMBER)  --參數的數據類型不能指定長度
AS
salary emp.sal%TYPE;
BEGIN
SELECT SAL INTO salary  FROM EMP WHERE EMPNO=eNo;
DBMS_OUTPUT.PUT_LINE(eNo||'號員工的工資為'||salary);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('沒有找到該編號的員工');
END;

當定義的存儲過程含有參數時,參數的數據類型不能指定長度。參數還有輸入和 輸出之分,本例中沒有指定,默認情況為輸入參數,也可顯示的指定某個參數是輸入參數,如(eNo IN NUMBER)。同示例1不同,該例中加入了異常處理。同示例1類似可以使用下面的兩種方式調用存儲過程:

BEGIN
getSalaryByEmpNo(7788);
END;

或者

EXEC getSalaryByEmpNo(7788);

或者

CALL getSalaryByEmpNo(7788);

但是如果傳給一個存儲過程的參數是變量時,必須使用BEGIN   END塊,如下:

DECLARE
no emp.empNo%TYPE;
BEGIN
no:=7788;
getSalaryByEmpNo(no);
END;

如果某個包中含有常量,也可以通過如下的方式調 用:

EXEC getSalaryByEmpNo(ConstantPackage.no);

但這種方式不能再使 用CALL調用。

示例4:創建含有輸入和輸出參數的存儲過程,該過程通過員工編號查找工資額, 工資額以輸出參數返回

CREATE OR REPLACE PROCEDURE getSalaryByEmpNo(eNo IN NUMBER,salary OUT NUMBER)
AS
BEGIN
SELECT SAL INTO salary  FROM EMP WHERE EMPNO=eNo;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('沒有 找到該編號的員工');
END;

當過程中含有輸出參數時,調用時必須通過BEGIN   END塊,不能通過EXEC或CALL調用。如:

DECLARE
salary NUMBER(7,2);
BEGIN
getSalaryByEmpNo(7788,salary);
DBMS_OUTPUT.PUT_LINE(salary);
END;

示例5:創建參數類型既是輸入參數也是輸出參數的過程

CREATE OR REPLACE PROCEDURE getSalaryByEmpNo(noSalary IN OUT NUMBER)
AS
BEGIN
SELECT SAL INTO noSalary  FROM EMP WHERE EMPNO=noSalary;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('沒有找到該編號的員工');
END;

調用 如下:

DECLARE
no NUMBER(7,2);
BEGIN
no:=7788;
getSalaryByEmpNo(no);
DBMS_OUTPUT.PUT_LINE(no);
END;

示例6:創建帶有默認值的過程

CREATE OR REPLACE PROCEDURE addEmp
(
empNo NUMBER,
eName VARCHAR2,
job   VARCHAR2 :='CLERK',
mgr   NUMBER,
hiredate DATE  DEFAULT SYSDATE,
sal  NUMBER    DEFAULT 1000,
comm  NUMBER    DEFAULT 0,
deptNo NUMBER  DEFAULT 30
)
AS
BEGIN
INSERT INTO emp VALUES(empNo,eName,job,mgr,hiredate,sal,comm,deptNo);
END;

調用如下: EXEC addEmp(7776,'zhangsan','CODER',7788,'06-1月- 2000',2000,0,10);  --沒有使用默認值
EXEC addEmp (7777,'lisi','CODER',7788,'06-1月-2000',2000,NULL,10);  --可以使用 NULL值
EXEC addEmp(7778,'wangwu',mgr=>7788);  --使用默認值
EXEC addEmp(mgr=>7788,empNo=>7779,eName=>'sunliu');  --更改參數順序

示例7:使用NOCOPY編譯提示

當參數是大型數據結構時,如集合、記錄和對象實 例,把它們的內容全部拷貝給形參會降低執行速度,消耗大量內存。為了防止這樣的情況發生,我們可 以使用 NOCOPY提示來讓編譯器按引用傳遞方式給IN OUT模式的參數。

DECLARE
TYPE DeptList IS TABLE OF VARCHAR2(10);
dList  DeptList:=DeptList ('CORESUN','CORESUN','CORESUN','CORESUN');
PROCEDURE My_Proc(d IN OUT NOCOPY DeptList)
AS...

注意:NOCOPY只是一個提示,而不是 指令。即使有時候我們使用了NOCOPY,但編譯器有可能仍然會進行值拷貝。通常情況下NOCOPY是可以成功 的。

二、維護過程

1、刪除存儲過程

DROP PROCEDURE Proc_Name;

2、查看過程狀態

SELECT object_name,status  FROM USER_OBJECTS WHERE object_type='PROCEDURE';

3、重新編譯過程

ALTER PROCEDURE Proc_Name COMPILE;

4、查看過程代碼

SELECT * FROM USER_SOURCE WHERE TYPE='PROCEDURE';

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved