|
發表者 |
討論內容 |
冷日 (冷日) |
發表時間:2019/5/30 14:29 |
- Webmaster

- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]ORACLE相關語法--子程序和程序包(package,function,procedure)
ORACLE相關語法--子程序和程序包(package,function,procedure) Oracle相關語法--子程序和程序包(package,function,procedure) 總結: 子程序是命名的PL/SQL塊,可帶參數並可在需要時隨時調用。 PL/SQL有兩種類型的子程序,即過程和函數。 過程用於執行特定的任務,函數用於執行任務並返回值。 程序包是對相關類型、變量、常量、遊標、異常、過程和函數的封裝。 程序包由包規範和包主體兩部分組成。 包規範是包的接口,包含公用對象及其類型。 包主體實現包規範中的遊標和子程序,包主體中的聲明僅限於在包內使用。 程序包中遊標的定義分為遊標規範和遊標主體兩部分。 語法及示例: 1、存儲過程 創建存儲過程的語法: CREATE [OR REPLACE] PROCEDURE procedure_name [(parameter_list)] {IS|AS} [local_declarations] BEGIN executable_statements [EXCEPTION exception_handlers] END [procedure_name]; 其中:procedure_name是過程的名稱。 parameter_list是參數列表。 local_declarations是局部聲明。 executable_statements是可執行語句。 exception_handlers是異常處理程序。 示例1:演示創建過程(參數列表中為IN參數賦予一個默認值,不能為OUT、IN OUT參數賦予默認值) create or replace procedure find_emp(emp_no in number:=7900) as empname varchar2(20); begin select ename into empname from emp where empno=emp_no; dbms_output.put_line('雇員姓名是 '||empname); exception when no_data_found then dbms_output.put_line('雇員編號未找到'); end find_emp; 調用過程:EXECUTE procudure_name(parameters_list); 也可以在過程裏面調用,直接寫上procudure_name而不必寫EXECUTE。 示例2:演示創建帶OUT參數的過程 create or replace procedure test(value1 varchar2,value2 out number) is identity number; begin select sal into identity from emp where empno=value1; if identity<2000 then value2:=1000; else value2:=500; end if; end; 調用帶OUT參數的過程: declare value2 number; begin test('7900',value2); dbms_output.put_line(value2); end; 示例3:演示創建帶IN OUT參數的過程 create or replace procedure swap(p1 in out number,p2 in out number) is v_temp number; begin v_temp:=p1; p1:=p2; p2:=v_temp; end; 調用帶IN OUT參數的過程: declare num1 number:=100; num2 number:=200; begin swap(num1,num2); dbms_output.put_line('num1= '||num1); dbms_output.put_line('num2= '||num2); end; 示例4:將過程的執行權限授予其他用戶 GRANT EXECUTE ON find_emp TO scott; GRANT EXECUTE ON swap TO PUBLIC; 將find_emp過程的執行權限授予給用戶scott,將執行swap過程的權限授予所有數據庫用戶。 刪除過程語法: DROP PROCEDURE procudure_name; 2、函數 定義函數的語法如下: CREATE [OR REPLACE] FUNCTION function_name [(parameter_list)] RETURN datatype {IS|AS} [local_declarations] BEGIN executable_statements [EXCEPTION exception_handlers] END [function_name]; 其中:function_name是函數的名稱。 parameter_list是參數列表。 local_declarations是局部聲明。 executable_statements是可執行語句。 exception_handlers是異常處理程序。 使用函數時註意:形式參數必須只使用數據庫類型,不得使用PL/SQL類型。函數的返回類型也必須是數據庫類型。 函數不能單獨執行,只能通過SQL語句或PL/SQL程序塊來調用。 示例5:演示如何創建函數 create or replace function fun_hello return varchar2 is begin return '朋友,您好'; end; 調用函數:select fun_hello from dual; 函數的授權:同過和的授權一樣具體請看示例4。 刪除函數:DROP FUNCTION function_name 過程和函數的差異 過程 函數 作為PL/SQL語句執行 作為表達式的一部分調用 在規範中不包含RETURN子句 必須在規範中包含RETURN子句 不返回任何值 必須返回單個值 可以包含RETURN語句,但是與函數不同,它不能用於返回值 必須包含至少一條RETURN語句 3、程序包 創建包規範的語法: CREATE [OR REPLACE] PACKAGE package_name IS|AS [Public type and item declarations] [Subprogram specifications] END [package_name]; 其中:package_name是包的名稱。 Public type and item declarations是聲明類型、常量、變量、異常和遊標等。 Subprogram specifications聲明PL/SQL子程序。 示例6:演示創建程序包規範 create or replace package pack_op is procedure pro_print_ename(id number); procedure pro_print_sal(id number); function fun_re_date(id number) return date; end; 創建包主體的語法: CREATE [OR REPLACE] PACKAGE BODY package_name IS|AS [Public type and item declarations] [Subprogram bodies] [BEGIN Initialization_statements] END [package_name]; 其中:package_name是包的名稱。 Public type and item declarations是聲明類型、常量、變量、異常和遊標等。 Subprogram bodies是定義公共和私有PL/SQL子程序。 示例7:演示創建程序包主體 create or replace package body pack_op is procedure pro_print_ename(id number) is name emp.ename%type; begin select ename into name from emp where empno=id; dbms_output.put_line('職員姓名:'||name); end pro_print_ename; procedure pro_print_sal(id number) is salary emp.sal%type; begin select sal into salary from emp where empno=id; dbms_output.put_line('職員工資:'||salary); end pro_print_sal; function fun_re_date(id number) return date is bedate emp.hiredate%type; begin select hiredate into bedate from emp where empno=id; return bedate; end fun_re_date; end pack_op; 示例8:調用程序包中創建的過程和函數 exec pack_op.pro_print_ename(7900); exec pack_op.pro_print_sal(7900); select pack_op.fun_re_date(7900) from dual; 示例9:演示程序包中的遊標 創建包規範 create or replace package pack_emp is cursor cur_emp return emp%rowtype; procedure pro_cur; end pack_emp; 創建包主體 create or replace package body pack_emp is cursor cur_emp return emp%rowtype is select * from emp; procedure pro_cur is rec_emp emp%rowtype; begin open cur_emp; loop fetch cur_emp into rec_emp; exit when cur_emp%notfound; if rec_emp.sal<1000 then dbms_output.put_line('員工工資:'||rec_emp.sal||',需加倍努力爭取提高工資'); elsif rec_emp.sal>=1000 and rec_emp.sal<2000 then dbms_output.put_line('員工工資:'||rec_emp.sal||',工資一般,爭取搞個部門經理做做'); else dbms_output.put_line('員工工資:'||rec_emp.sal||',工資不錯,爭取搞個總經理做做'); end if; end loop; end pro_cur; end pack_emp; 調用程序包中的過程以調用程序包中的遊標 exec pack_emp.pro_cur; 示例10:存儲過程返回遊標的子程序包(此程序包返回r_cur遊標) CREATE OR REPLACE package SCOTT.pk_wt is type mytype is ref cursor; procedure p_wt(mycs out mytype); end; CREATE OR REPLACE package BODY SCOTT.pk_wt is procedure p_wt(mycs out mytype) is r_cur mytype; begin open r_cur for select * from emp; mycs:=r_cur; end p_wt; end pk_wt; 查詢有關過程、函數和程序包的信息:USER_OBJECTS數據字典視圖 column object_name format a18 select object_name,object_type from user_objects where object_type in ('PROCEDURE','FUNCTION','PACKAGE','PACKAGE BODY'); 原文出處:ORACLE相關語法--子程序和程序包(package,function,procedure) - IT閱讀
|
|
冷日 (冷日) |
發表時間:2019/5/30 14:31 |
- Webmaster

- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]CREATE PACKAGE BODY介紹
CREATE PACKAGE BODY介紹 語法說明 - 執行CREATE PACKAGE BODY句可建立程式包裝的本體部分,指定 [OR REPLACE] 可重建已建立的程式包裝本體部分,此時不必再次授與該程式包裝的物件權限,也不必再次授與物件權限給己獲此權限的使用者,程式包裝本體部分描述程式包裝成員 [預儲程式和預儲數的處理內容]
格式 CREATE [ OR REPLACE] PACKAGE BODY [schema.]package_name { IS | AS} package_specification END [package_name]; schema : 結構名稱 package_name : 程式包裝名稱 package_specification : 程式包裝規格,類型定義,指標/變數/常數/例外的聲明,PL/SQL子程式的規格和PL/SQL內部紀錄的(或者是)java常式的聲明(叫用規格)等 語法示範
說明 : 建立預儲程式包裝emp_mgmt的程式包裝本體部分 create or replace package body emp_mgmt as tot_emps NUMBER; tot_depts NUMBER; FUNCTION hire (last_name VARCHAR2, job_id VARCHAR2, manager_id NUMBER, salary NUMBER, commission_pct NUMBER, department_id NUMBER) RETURN NUMBER IS new_empno NUMBER; BEGIN SELECT employees_seq.NEXTVAL INTO new_empno FROM DUAL; INSERT INTO employees VALUES (new_empno, 'First', 'Last','first.last@oracle.com', '(123)123-1234','18-JUN-02','IT_PROG',90000000,00, 100,110); tot_emps := tot_emps + 1; RETURN(new_empno); END; FUNCTION create_dept(department_id NUMBER, location_id NUMBER) RETURN NUMBER IS new_deptno NUMBER; BEGIN SELECT departments_seq.NEXTVAL INTO new_deptno FROM dual; INSERT INTO departments VALUES (new_deptno, 'department name', 100, 1700); tot_depts := tot_depts + 1; RETURN(new_deptno); END; PROCEDURE remove_emp (employee_id NUMBER) IS BEGIN DELETE FROM employees WHERE employees.employee_id = remove_emp.employee_id; tot_emps := tot_emps - 1; END; PROCEDURE remove_dept(department_id NUMBER) IS BEGIN DELETE FROM departments WHERE departments.department_id = remove_dept.department_id; tot_depts := tot_depts - 1; SELECT COUNT(*) INTO tot_emps FROM employees; END; PROCEDURE increase_sal(employee_id NUMBER, salary_incr NUMBER) IS curr_sal NUMBER; BEGIN SELECT salary INTO curr_sal FROM employees WHERE employees.employee_id = increase_sal.employee_id; IF curr_sal IS NULL THEN RAISE no_sal; ELSE UPDATE employees SET salary = salary + salary_incr WHERE employee_id = employee_id; END IF; END; PROCEDURE increase_comm(employee_id NUMBER, comm_incr NUMBER) IS curr_comm NUMBER; BEGIN SELECT commission_pct INTO curr_comm FROM employees WHERE employees.employee_id = increase_comm.employee_id; IF curr_comm IS NULL THEN RAISE no_comm; ELSE UPDATE employees SET commission_pct = commission_pct + comm_incr; END IF; END; END emp_mgmt; / 原文出處:Oracle SQL學習筆記本: CREATE PACKAGE BODY介紹
|
|
|
冷日 (冷日) |
發表時間:2019/5/30 14:36 |
- Webmaster

- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]學習初級Oracle PL/SQL
學習初級Oracle PL/SQL (三) Packages
在練習中 , 你很少創建一個獨立的存儲 function 或 procedure. 相反 , 你會使用 package. 什麼是 package? Package 是組織相關的 function 和 procedure 包含 在一起 , 就像創建一個圖書館 , 但在 PL/SQL 術語中稱為 package. 當你 建立 Procedure 或 Function 後會 保存 在 Oracle 的 Procedure 與Function 目錄裡 , 如果我有一個 Procedure 功能與已存在的 Procedure 類似 , 但又有點不一樣 , Oracle 又不允許在 Procedure 目錄下建立相同名稱的 Procedure, 這時候就要靠 Package 來把相同名稱的 Procedure 分開 . Package 也有分類的意思 , 將相關功能模組封裝在同一個 Package 內可提高聚合性 .
PL/SQL Package 有兩部分 : 1. Package specification 2. Package body
Package Specification 定義了此 Package 內所有的成員 , 例如 :Procedure 與 Function, 這裡定義的Procedure 與 Function 只要擺定義即可不需要放實作的內容 , 在 Specification 的成員都是對外公開 Public. Package Body 為放置成員 Spec 的詳細實作區 , 在建立 Package 時要先有 Specification 才可以有 Body, 你可以將 Spec 與 Body 分成兩個檔案撰寫也可以撰寫在同一個檔案裡 .
Package Specification 語法 : CREATE [OR REPLACE] PACKAGE <package_name> AS -- one or more: constant, cursor, function, procedure, or variable declarations END <package_name>; /
Create package spec. 以下 Package spec 例子 , 包含了 5 個 functions, 但只有 declare 並沒有運行 code, code 在 package body. create or replace package date_ as d_max constant date:= to_date('99991231','YYYYMMDD'); d_min constant date:= to_date('19900101','YYYYMMDD'); -- 常數關鍵字 constant. 它需要一個初始值 , 並且不允許被改變該值 .
function end_of_day( input1in date) return date;
function get_max return date;
function get_min return date;
function random ( starting_year in number, ending_year in number) return date ;
function start_of_day( input2 in date) return date;
end date_; / |
Create package body: create or replace package body date_ as
function end_of_day(input1 in date) return date as begin return to_date( to_char(input1, 'YYYYMMDD')||'235959','SYYYYMMDDHH24MISS'); end end_of_day;
function get_max return date as begin returnd_max; end get_max;
function get_min return date as begin returnd_min; end get_min;
function random (starting_year in number, ending_year in number) return date as d_random date; n_day number; n_month number; n_year number; begin n_year := round(dbms_random. value(starting_year,ending_year),0); n_month := round(dbms_random.value(1,12),0); n_day := round(dbms_random.value(1,31),0); d_random := to_date(lpad(to_char(n_year),4,'0')|| lpad(to_char(n_month),2,'0')|| lpad(to_char(n_day),2,'0'),'YYYYMMDD'); exception when others then pl( SQLERRM ); end; return d_random; end random;
function start_of_day(input2 in date) return date as begin return trunc(input2); endstart_of_day; enddate_; / |
執行效果 :
SQL> alter session set nls_date_format='YYYYMMDDHH24MISS';
Session altered.
SQL> select date_.end_of_day(sysdate) from dual;
DATE_.END_OF_D -------------- 20160725235959
SQL> select date_.get_max from dual;
GET_MAX -------------- 99991231000000
SQL> select date_.get_min from dual;
GET_MIN -------------- 19900101000000
SQL> select date_.random(1994,2014) from dual;
DATE_.RANDOM(1 -------------- 19960809000000
SQL> select date_.start_of_day('20160101235959') from dual;
DATE_.START_OF -------------- 20160101000000
I t’s Your turn to Create a package 還記得較早前創建的 to_number2 function 嗎 ? 用它來創建你的 package 吧 . 條款如下 : 1. Package 名稱 NUMBER_ 2. 用 select 來測試 package.
PL/SQL BLOCK 語法比較 ANONYMOUS [DECLARE] | CREATE FUNCTION | CREATE PROCEDURE | CREATE PACKAGE | CREATE PACKAGE BODY | - | [parameters] | [parameters] | - | - | - | RETURN | - | - | - | [declaration section] | [declaration section] | [declaration section] | [declaration section] | [declaration section] | BEGIN | BEGIN | BEGIN | - | BEGIN | executable section | executable section | executable section | - | executable section | [EXCEPTION] | [EXCEPTION] | [EXCEPTION] | - | [EXCEPTION] | [exception handling] | [exception handling] | [exception handling] | - | [exception handling] | END; | END; | END; | END; | END; | / | / | / | / | / |
原文出處:Alan Yeung 的學習 Blog: 學習初級Oracle PL/SQL (三)
|
|
冷日 (冷日) |
發表時間:2019/5/30 14:39 |
- Webmaster

- 註冊日: 2008/2/19
- 來自:
- 發表數: 15771
|
- [轉貼]Oracle 中 dual 表的用途
dual是一個虛擬表,用來構成select的語法規則,oracle保證dual裡面永遠只有一條記錄。 我們可以用它來做很多事情,如下: 1、查看當前使用者,可以在 SQL Plus中執行下面語句 select user from dual; 2、用來調用系統函數 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;--獲得當前系統時間 select SYS_CONTEXT('USERENV','TERMINAL') from dual;--獲得主機名稱 select SYS_CONTEXT('USERENV','language') from dual;--獲得當前 locale select dbms_random.random from dual;--獲得一個亂數 3、得到序列的下一個值或當前值,用下面語句 select your_sequence.nextval from dual;--獲得序列your_sequence的下一個值 select your_sequence.currval from dual;--獲得序列your_sequence的當前值 4、可以用做計算機 select 7*9 from dual;
------ Oracle系統中dual表是一個「神秘」的表,網上有很多網友都對該表進行了測試,該表只有一行一列,其實該表和系統中的其他表一樣,一樣可以執行插入、更新、刪除操作,還可以執行drop操作。 但是不要去執行drop表的操作,否則會使系統不能用,資料庫起不了,會報Database startup crashes with ORA-1092錯誤。 此時也不要慌亂,可以通過執行以下步驟來進行恢復。 可以用sys使用者登陸。 SQL> create pfile=’d:pfile.bak’ from spfile SQL> shutdown immediate 在d:pfile.bak檔中最後加入一條: replication_dependency_tracking = FALSE 重新開機資料庫: SQL> startup pfile=’d:pfile.bak’ SQL> create table 「sys」.」 DUAL」 [an error occurred while processing this directive] ===== DUAL ? 有什麼神秘的? 當你想得到ORACLE系統時間, 簡簡單單敲一行SQL 不就得了嗎? 故弄玄虛.... SQL> select sysdate from dual; SYSDATE --------- 28-SEP-03 哈哈, 確實DUAL的使用很方便. 但是大家知道DUAL倒底是什麼OBJECT, 它有什麼特殊的行為嗎? 來,我們一起看一看. 首先搞清楚DUAL是什麼OBJECT : SQL> connect system/manager Connected. SQL> select owner, object_name , object_type from dba_objects where object_name like '%DUAL%'; OWNER OBJECT_NAME OBJECT_TYPE --------------- --------------- ------------- SYS DUAL TABLE PUBLIC DUAL SYNONYM 原來DUAL是屬於SYS schema的一個表,然後以PUBLIC SYNONYM的方式供其他資料庫USER使用.
再看看它的結構: SQL> desc dual Name Null? Type ----------------------------------------- -------- ---------------------------- DUMMY VARCHAR2(1) SQL> 只有一個名字叫DUMMY的字元型COLUMN . 然後查詢一下表裡的資料: SQL> select dummy from dual; DUMMY ---------- X 哦, 只有一條記錄, DUMMY的值是’X’ .很正常啊,沒什麼奇怪嘛. 好,下面就有奇妙的東西出現了! 插入一條記錄: SQL> connect sys as sysdba Connected. SQL> insert into dual values ( 'Y');
1 row created. SQL> commit; Commit complete. SQL> select count(*) from dual; COUNT(*) ---------- 2 迄今為止,一切正常. 然而當我們重新查詢記錄時,奇怪的事情發生了 SQL> select * from dual; DUMMY ---------- X 剛才插入的那條記錄並沒有顯示出來 ! 明明DUAL表中有兩條記錄, 可就是只顯示一條! 再試一下刪除 ,狠一點,全刪光 ! SQL> delete from dual; /*注意沒有限定條件,試圖刪除全部記錄*/ 1 row deleted. SQL> commit;
Commit complete. 哈哈,也只有一條記錄被刪掉, SQL> select * from dual; DUMMY ---------- Y 為什麼會這樣呢? 難道SQL的語法對DUAL不起作用嗎?帶著這個疑問, 我查詢了一些ORACLE官方的資料. 原來ORACLE對DUAL表的操作做了一些內部處理,儘量保證DUAL表中只返回一條記錄.當然這寫內部操作是不可見的 . 看來ORACLE真是蘊藏著無窮的奧妙啊! 原文出處:Oracle中dual表的用途 @ 資訊園 :: 痞客邦 ::
|
|
|
|