定義新存儲過程。
語法
CREATE [OR REPLACE] PROCEDURE name [ (parameters) ]
[
IMMUTABLE
| STABLE
| VOLATILE
| DETERMINISTIC
| [ NOT ] LEAKPROOF
| CALLED ON NULL INPUT
| RETURNS NULL ON NULL INPUT
| STRICT
| [ EXTERNAL ] SECURITY INVOKER
| [ EXTERNAL ] SECURITY DEFINER
| AUTHID DEFINER
| AUTHID CURRENT_USER
| PARALLEL { UNSAFE | RESTRICTED | SAFE }
| COST execution_cost
| ROWS result_rows
| SET configuration_parameter
{ TO value | = value | FROM CURRENT }
...]
{ IS | AS }
[ PRAGMA AUTONOMOUS_TRANSACTION; ]
[ declarations ]
BEGIN
statements
END [ name ];
說明
CREATE PROCEDURE 可定義新存儲過程。CREATE OR REPLACE PROCEDURE 將創建新的存儲過程或替換現有定義。
如果包括 schema 名稱,則在指定的 schema 中創建存儲過程。否則在當前 schema 中創建。新存儲過程的名稱不得與同一 schema 中具有相同輸入參數類型的任何現有存儲過程匹配。不過,具有不同輸入參數類型的存儲過程可共用一個名稱(這稱為重載)。(存儲過程重載是一項 PolarDB PostgreSQL版(兼容Oracle)功能 - 獨立存儲過程的重載與 Oracle 數據庫不兼容。)
要更新現有存儲過程的定義,可使用 CREATE OR REPLACE PROCEDURE。無法以這種方式更改存儲過程的名稱或參數類型(如果您嘗試過,實際上創建的是一個新的不同存儲過程)。使用 OUT 參數時,除非通過刪除存儲過程,否則不能更改任何 OUT 參數的類型。
參數
參數 | 說明 |
---|---|
name | name 是存儲過程的標識符。 |
parameters | parameters 是形參的列表。 |
declarations | declarations 是變量、游標、類型或子程序聲明。如果包括子程序聲明,則它們必須在所有其他變量、游標和類型聲明之后。 |
statements | statements 是 SPL 程序語句(BEGIN - END 塊可以包含 EXCEPTION 部分)。 |
IMMUTABLE | STABLE | VOLATILE | 這些屬性將存儲過程的行為通知給查詢優化器;您只能指定一個選項。VOLATILE 是默認行為。
|
DETERMINISTIC | DETERMINISTIC 是 IMMUTABLE 的同義詞。DETERMINISTIC 存儲過程不能修改數據庫,并在提供相同參數值時始終會得到相同結果;它不執行數據庫查找,也不以其他方式使用其參數列表中不直接存在的信息。如果包括此子句,則使用全常量參數對存儲過程的任何調用將立即替換為存儲過程值。 |
[ NOT ] LEAKPROOF | LEAKPROOF 存儲過程沒有負面影響,也不會公開有關調用存儲過程所用值的任何信息。 |
CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT |
|
[ EXTERNAL ] SECURITY DEFINER | SECURITY DEFINER 指定存儲過程將使用創建它的用戶的特權來執行。這是默認值。為了符合 SQL 要求,允許使用關鍵字 EXTERNAL,但這是可選的。 |
[ EXTERNAL ] SECURITY INVOKER | SECURITY INVOKER 子句指示存儲過程將使用調用它的用戶的特權執行。為了符合 SQL 要求,允許使用關鍵字 EXTERNAL,但這是可選的。 |
AUTHID DEFINER | AUTHID CURRENT_USER |
|
PARALLEL { UNSAFE | RESTRICTED | SAFE } | 通過 PARALLEL 子句可以使用并行順序掃描(并行模式)。在查詢期間,相比串行順序掃描,并行順序掃描使用多個工作線程并行掃描一個關系。
|
COST execution_cost | execution_cost 是一個正數,給出該存儲過程的估計執行成本,單位為 cpu_operator_cost。如果存儲過程返回一個集合,則這是每個返回行的成本。較大值會導致計劃程序嘗試避免超出必要的頻率來對函數求值。 |
ROWS result_rows | result_rows 是一個正數,給出計劃程序預計存儲過程返回的估計行數。僅當存儲過程聲明為返回一個集合時,才允許這么做。默認假定值為 1000 行。 |
SET configuration_parameter { TO value | = value | FROM CURRENT } | SET 子句使指定的配置參數在進入存儲過程時設置為指定值,然后在存儲過程退出時恢復為其之前的值。SET FROM CURRENT 將會話的當前參數值保存為進入存儲過程時要應用的值。 如果將 SET 子句附加到存儲過程,則在存儲過程內針對相同變量執行 SET LOCAL 命令的效果僅限于該存儲過程。存儲過程退出時配置參數將恢復為之前的值。普通的 SET 命令(沒有 LOCAL)會重寫 SET 子句,與對之前 SET LOCAL 命令的操作很相似,此命令的效果在退出存儲過程后會保留,除非回滾當前事務。 |
PRAGMA AUTONOMOUS_TRANSACTION | PRAGMA AUTONOMOUS_TRANSACTION 是將存儲過程設置為自治事務的指令。 |
- STRICT、LEAKPROOF、PARALLEL、COST、ROWS 和 SET 關鍵字可以為PolarDB PostgreSQL版(兼容Oracle)提供擴展功能,但 Oracle 不支持這些關鍵字。
- 只有PolarDB PostgreSQL版(兼容Oracle)存儲過程支持 IMMUTABLE、STABLE、STRICT、LEAKPROOF、COST、ROWS 及 PARALLEL { UNSAFE | RESTRICTED | SAFE } 屬性。
- 默認情況下存儲過程創建為 SECURITY DEFINERS。在 plpgsql 中定義的存儲過程創建為 SECURITY INVOKERS。
示例
以下存儲過程列出了 emp 表中的員工:
CREATE OR REPLACE PROCEDURE list_emp
IS
v_empno NUMBER(4);
v_ename VARCHAR2(10);
CURSOR emp_cur IS
SELECT empno, ename FROM emp ORDER BY empno;
BEGIN
OPEN emp_cur;
DBMS_OUTPUT.PUT_LINE('EMPNO ENAME');
DBMS_OUTPUT.PUT_LINE('----- -------');
LOOP
FETCH emp_cur INTO v_empno, v_ename;
EXIT WHEN emp_cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_ename);
END LOOP;
CLOSE emp_cur;
END;
EXEC list_emp;
EMPNO ENAME
----- -------
7369 SMITH
7499 ALLEN
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7844 TURNER
7876 ADAMS
7900 JAMES
7902 FORD
7934 MILLER
以下存儲過程使用 IN OUT 和 OUT 參數返回員工的編號、姓名和職位,首先采用給定的員工編號進行搜索,如果找不到則采用給定的姓名。一個匿名塊調用該存儲過程。
CREATE OR REPLACE PROCEDURE emp_job (
p_empno IN OUT emp.empno%TYPE,
p_ename IN OUT emp.ename%TYPE,
p_job OUT emp.job%TYPE
)
IS
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_job emp.job%TYPE;
BEGIN
SELECT ename, job INTO v_ename, v_job FROM emp WHERE empno = p_empno;
p_ename := v_ename;
p_job := v_job;
DBMS_OUTPUT.PUT_LINE('Found employee # ' || p_empno);
EXCEPTION
WHEN NO_DATA_FOUND THEN
BEGIN
SELECT empno, job INTO v_empno, v_job FROM emp
WHERE ename = p_ename;
p_empno := v_empno;
p_job := v_job;
DBMS_OUTPUT.PUT_LINE('Found employee ' || p_ename);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Could not find an employee with ' ||
'number, ' || p_empno || ' nor name, ' || p_ename);
p_empno := NULL;
p_ename := NULL;
p_job := NULL;
END;
END;
DECLARE
v_empno emp.empno%TYPE;
v_ename emp.ename%TYPE;
v_job emp.job%TYPE;
BEGIN
v_empno := 0;
v_ename := 'CLARK';
emp_job(v_empno, v_ename, v_job);
DBMS_OUTPUT.PUT_LINE('Employee No: ' || v_empno);
DBMS_OUTPUT.PUT_LINE('Name : ' || v_ename);
DBMS_OUTPUT.PUT_LINE('Job : ' || v_job);
END;
Found employee CLARK
Employee No: 7782
Name : CLARK
Job : MANAGER
以下示例演示了如何在存儲過程聲明中使用 AUTHID DEFINER 和 SET 子句。update_salary 存儲過程將定義了該存儲過程的角色的特權傳遞給正在調用該存儲過程的角色(在執行該存儲過程時):
CREATE OR REPLACE PROCEDURE update_salary(id INT, new_salary NUMBER)
SET SEARCH_PATH = 'public' SET WORK_MEM = '1MB'
AUTHID DEFINER IS
BEGIN
UPDATE emp SET salary = new_salary WHERE emp_id = id;
END;
包括 SET 子句,將存儲過程的搜索路徑設置為 public,并將工作內存設置為 1MB。其他存儲過程、函數及對象不受這些設置的影響。
在此示例中,AUTHID DEFINER 子句將特權臨時授予可能不允許執行存儲過程內語句的角色。要指示服務器使用與調用存儲過程的角色相關聯的特權,可將 AUTHID DEFINER 子句替換為 AUTHID CURRENT_USER 子句。