茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1670403 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_00045.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

DB研討會 : [轉貼]ORACLE相關語法--子程序和程序包(package,function,procedure)

發表者 討論內容
冷日
(冷日)
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閱讀
冷日
(冷日)
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介紹
冷日
(冷日)
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 (三)
冷日
(冷日)
Webmaster
  • 註冊日: 2008/2/19
  • 來自:
  • 發表數: 15771
[轉貼]Oracle 中 dual 表的用途

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表的用途 @ 資訊園 :: 痞客邦 ::
前一個主題 | 下一個主題 | 頁首 | | |



Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|