1. 程式人生 > >Oracle 儲存過程 陣列

Oracle 儲存過程 陣列

Oracle儲存過程 一維陣列 二維陣列 (範例)

/*
在PL/SQL中是沒有陣列(Array)概念的。但是如果程式設計師想用Array的話,就得變通一下,用TYPE 和Table of Record來代替多維陣列,一樣挺好用的。

emp_type 就好象一個table 中的一條record 一樣,裡面有id, name,gender等。emp_type_array 象個table, 裡面含有一條條這樣的record (emp_type),就象多維陣列一樣。
*/

--單維陣列
/*
DECLARE
TYPE emp_ssn_array IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;

best_employees emp_ssn_array;
worst_employees emp_ssn_array;

BEGIN
best_employees(1) := '123456';
best_employees(2) := '888888';

worst_employees(1) := '222222';
worst_employees(2) := '666666';

FOR i IN 1..best_employees.count LOOP
DBMS_OUTPUT.PUT_LINE('i='|| i || ', best_employees= ' ||best_employees(i)
|| ', worst_employees= ' ||worst_employees(i));
END LOOP;

END;
*/

--多維陣列
DECLARE

TYPE emp_type IS RECORD

emp_id scott.emp.empno%TYPE,
emp_name scott.emp.ename%TYPE,
emp_job scott.emp.job%TYPE );

TYPE emp_type_array IS TABLE OF emp_type INDEX BY BINARY_INTEGER;

emp_rec_array emp_type_array;
emp_rec emp_type;

BEGIN
emp_rec.emp_id := 7788;
emp_rec.emp_name := 'Barbara';
emp_rec.emp_job := 'Female';

emp_rec_array(1) := emp_rec;

emp_rec.emp_id := 7900;
emp_rec.emp_name := 'Rick';
emp_rec.emp_job := 'Male';

emp_rec_array(2) := emp_rec;

FOR i IN 1..emp_rec_array.count LOOP
DBMS_OUTPUT.PUT_LINE('i='||i
||', emp_id ='||emp_rec_array(i).emp_id
||', emp_name ='||emp_rec_array(i).emp_name
||', emp_job = '||emp_rec_array(i).emp_job);
END LOOP; 

END;

 

https://blog.csdn.net/huanyingfengxing/article/details/41008143

 

 

 

 

 

Oracle儲存過程 陣列集合的使用

2017年07月28日 09:51:59 芒果燉牛肉 閱讀數:5876 標籤: 儲存過程ORACLE集合 更多

個人分類: Oracle

--轉自:http://blog.csdn.net/liangweiwei130/article/details/38223319#comments

1     說明

1.1       RECORD

定義記錄資料型別。它類似於C語言中的結構資料型別(STRUCTURE),PL/SQL提供了將幾個相關的、分離的、基本資料型別的變數組成一個整體的方法,即RECORD複合資料型別。在使用記錄資料型別變數時,需要在宣告部分先定義記錄的組成、記錄的變數,然後在執行部分引用該記錄變數本身或其中的成員。

   定義記錄資料型別的語法如下:

TYPE RECORD_NAME IS RECORD(

V1 DATA_TYPE1 [NOT NULL][:=DEFAULT_VALUE],

V2 DATA_TYPE2 [NOT NULL][:=DEFAULT_VALUE],

VN DATA_TYPEN [NOT NULL][:=DEFAULT_VALUE]);

1.2       VARRAY

陣列是具有相同資料型別的一組成員的集合。每個成員都有一個唯一的下標,它取決於成員在陣列中的位置。在PL/SQL中,陣列資料型別是VARRAY(variable array,即可變陣列)。

定義VARRAY資料型別的語法如下:

TYPE VARRAY_NAMEIS VARRAY(SIZE) OF ELEMENT_TYPE [NOT NULL];

其中,varray_name是VARRAY資料型別的名稱,size是正整數,表示可以容納的成員的最大數量,每個成員的資料型別是element_typeo預設時,成員可以取空值,否則需要使用NOT NULL加以限制。

 

1.3       TABLE

定義記錄表(或索引表)資料型別。它與記錄型別相似,但它是對記錄型別的擴充套件。它可以處理多行記錄,類似於C語言中的二維陣列,使得可以在PL/SQL中模仿資料庫中的表。

定義記錄表型別的語法如下:

TYPE TABLE NAME IS TABLE OF ELEMENT_TYPE [NOT NULL]

INDEX BY [BINARY_INTEGER|PLS_INTEGER|VARRAY2];

關鍵字INDEX BY表示建立一個主鍵索引,以便引用記錄表變數中的特定行。

BINARY_INTEGER的說明

如語句:TYPE NUMBERS  IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;其作用是,加了”INDEX BYBINARY_INTEGER ”後,NUMBERS型別的下標就是自增長,NUMBERS型別在插入元素時,不需要初始化,不需要每次EXTEND增加一個空間。

而如果沒有這句話“INDEXBY BINARY_INTEGER”,那就得要顯示對初始化,且每插入一個元素到NUMBERS型別的TABLE中時,都需要先EXTEND。

 

2     舉例

2.1       建立表結構以及資料準備

 

[sql] view plain copy

  1. --組織機構結構表  
  2. CREATE TABLE SF_ORG  
  3. (  
  4. ORG_ID INT NOT NULL, --組織機構主鍵ID  
  5. ORG_NAME VARCHAR2(50),--組織機構名稱  
  6. PARENT_ID INT--組織機構的父級  
  7. )  
  8.   
  9. --一級組織機構  
  10. INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(1, '一級部門1',0);  
  11.   
  12. --二級部門  
  13.   
  14. INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(2, '二級部門2',1);  
  15. INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(3, '二級部門3',1);  
  16. INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(4, '二級部門4',1);  

 

2.2       RECORD的使用舉例

先定義一個只與SF_ORG表中某幾個列的資料型別相同的記錄資料型別TYPE_ORG_RECORD,然後宣告一個該資料型別的記錄變數V_ORG_RECORD,最後用替換變數&ORG_ID接受輸入的僱員編碼,查詢並顯示該僱員的這幾列中的資訊。注意,在使用RECORD資料型別的變數時要用“.”運算子指定記錄變數名限定詞。

   一個記錄型別的變數只能儲存從資料庫中查詢出的一行記錄,如果查詢出了多行記錄,就會出現錯誤。

 

[sql] view plain copy

  1. DECLARE   
  2.   TYPE TYPE_ORG_RECORD IS RECORD(  
  3.   V_ORG_NAME SF_ORG.ORG_NAME%TYPE,  
  4.   V_PARENT_ID SF_ORG.PARENT_ID%TYPE);  
  5.   V_ORG_RECORD TYPE_ORG_RECORD;  
  6. BEGIN  
  7.   SELECT ORG_NAME,PARENT_ID INTO V_ORG_RECORD  
  8.   FROM SF_ORG SO  
  9.   WHERE SO.ORG_ID=&ORG_ID;  
  10.   DBMS_OUTPUT.PUT_LINE('部門名稱:' || V_ORG_RECORD.V_ORG_NAME);  
  11.   DBMS_OUTPUT.PUT_LINE('上級部門編碼:' || TO_CHAR(V_ORG_RECORD.V_PARENT_ID));  
  12. END;  

 

2.3       VARRAY的使用舉例

先定義一個能儲存5個VARCHAR2(25)資料型別的成員的VARRAY資料型別ORG_VARRAY_TYPE,然後宣告一個該資料型別的VARRAY變數V_ORG_VARRAY,最後用與ORG_VARRAY_TYPE資料型別同名的建構函式語法給V_ORG_VARRAY變數賦予初值並顯示賦值結果。

注意,在引用陣列中的成員時.需要在一對括號中使用順序下標,下標從1開始而不是從0開始。

 

[sql] view plain copy

  1. DECLARE   
  2.   TYPE ORG_VARRAY_TYPE IS VARRAY(5) OF VARCHAR2(25);  
  3.   V_ORG_VARRAY ORG_VARRAY_TYPE;  
  4. BEGIN  
  5.   V_ORG_VARRAY := ORG_VARRAY_TYPE('1','2','3','4','5');  
  6.   DBMS_OUTPUT.PUT_LINE('輸出1:' || V_ORG_VARRAY(1) || '、'|| V_ORG_VARRAY(2) || '、'|| V_ORG_VARRAY(3) || '、'|| V_ORG_VARRAY(4));  
  7.   DBMS_OUTPUT.PUT_LINE('輸出2:' || V_ORG_VARRAY(5));  
  8.   V_ORG_VARRAY(5) := '5001';  
  9.   DBMS_OUTPUT.PUT_LINE('輸出3:' || V_ORG_VARRAY(5));  
  10. END;  

 

2.4       TABLE使用舉例

2.4.1      儲存單列多行

這個和VARRAY類似。但是賦值方式稍微有點不同,不能使用同名的建構函式進行賦值。具體的如下:

 

[sql] view plain copy

  1. DECLARE   
  2.   TYPE ORG_TABLE_TYPE IS TABLE OF VARCHAR2(25)  
  3.   INDEX BY BINARY_INTEGER;  
  4.   V_ORG_TABLE ORG_TABLE_TYPE;  
  5. BEGIN  
  6.   V_ORG_TABLE(1) := '1';  
  7.   V_ORG_TABLE(2) := '2';  
  8.   V_ORG_TABLE(3) := '3';  
  9.   V_ORG_TABLE(4) := '4';  
  10.   V_ORG_TABLE(5) := '5';  
  11.   DBMS_OUTPUT.PUT_LINE('輸出1:' || V_ORG_TABLE(1) || '、'|| V_ORG_TABLE(2) || '、'|| V_ORG_TABLE(3) || '、'|| V_ORG_TABLE(4));  
  12.   DBMS_OUTPUT.PUT_LINE('輸出2:' || V_ORG_TABLE(5));  
  13. END;  

 

2.4.2      儲存多列多行和ROWTYPE結合使用

採用bulkcollect可以將查詢結果一次性地載入到collections中。而不是通過cursor一條一條地處理。

 

[sql] view plain copy

  1. DECLARE   
  2.    TYPE T_TYPE IS TABLE OF SF_ORG%ROWTYPE;  
  3.    V_TYPE  T_TYPE;  
  4.  BEGIN  
  5.     SELECT ORG_ID,ORG_NAME,PARENT_ID BULK COLLECT INTO V_TYPE  
  6.     FROM SF_ORG  
  7.     WHERE SF_ORG.ORG_ID <= 3;  
  8.   
  9.     FOR V_INDEX IN V_TYPE.FIRST .. V_TYPE.LAST LOOP  
  10.         DBMS_OUTPUT.PUT_LINE(V_TYPE(V_INDEX).C1 || ' ' || V_TYPE(V_INDEX).C2);  
  11.     END LOOP;  
  12.  END;  

 

2.4.3      儲存多列多行和RECORD結合使用

採用bulkcollect可以將查詢結果一次性地載入到collections中。而不是通過cursor一條一條地處理。

 

[sql] view plain copy

  1. DECLARE   
  2.    TYPE TEST_EMP IS RECORD  
  3.    (  
  4.     C1 SF_ORG.ORG_NAME%TYPE,  
  5.     C2 SF_ORG.PARENT_ID%TYPE  
  6.    );     
  7.    TYPE T_TYPE IS TABLE OF TEST_EMP;  
  8.    V_TYPE  T_TYPE;  
  9.  BEGIN  
  10.     SELECT ORG_NAME,  PARENT_ID BULK COLLECT INTO V_TYPE  
  11.     FROM SF_ORG  
  12.     WHERE SF_ORG.ORG_ID <= 3;  
  13.   
  14.     FOR V_INDEX IN V_TYPE.FIRST .. V_TYPE.LAST LOOP  
  15.         DBMS_OUTPUT.PUT_LINE(V_TYPE(V_INDEX).C1 || ' ' || V_TYPE(V_INDEX).C2);  
  16.     END LOOP;  
  17.  END;  

https://blog.csdn.net/redBeefNoodles/article/details/76228472

 

 

 

Oracle儲存過程例子:運用了正則表示式、陣列等

程式碼

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->CREATE OR REPLACE PROCEDURE "SP_GET_ARTICLE_DATA"
(article_detail_id_$ number,
Record_Md5_ID_$ varchar2,
content_text_$ clob,
ReturnValue out number
) is
begin
declare
--自定義陣列
TYPE StringArray IS table OF VARCHAR2(1000);

Offset_URL number;
Offset_Email number;
Offset_Phone number;
Offset_Account number;

--資料下標
URL_V_Num number:=1;
Email_V_Num number:=1;
Phone_V_Num number:=1;
Account_V_Num number:=1;

--資料元素存在標誌
Is_Exsit_Flag number;

URL varchar2(3000);
Email varchar2(200);
Phone varchar2(100);
Bank_Account varchar2(100);

URL_Array StringArray:=StringArray();
Email_Array StringArray:=StringArray();
Phone_Array StringArray:=StringArray();
Account_Array StringArray:=StringArray();

--常量
URL_RegExp constant varchar2(300):='(((file|gopher|news|nntp|telnet|http|ftp|https|ftps|sftp)://)|(www\.))+(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(/[a-zA-Z0-9\&'||'%_\./-~-]*)?';
Email_RegExp constant varchar2(200):='[A-Za-z0-9_]+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*';
Phone_RegExp constant varchar2(300):='[+[:digit:]]{1,2}[-\.,[:blank:]]*\d{3}[-\.,[:blank:]]*\d{3}[-\.,[:blank:]]*\d{4}|[+[:digit:]]?[-\.,[:blank:]]*\d{1,2}[-\.,[:blank:]]*\d{3}[-\.,[:blank:]]+\d{4}|\d{3}[-\.,[:blank:]]+\d{4}';
Bank_Account_RegExp constant varchar2(200):='(SA)?[[:digit:]]{22}|(SA)?[[:blank:]]*([[:digit:]]{4}|\d{2})[-\.,[:blank:]]*[[:digit:]]{4}[-\.,[:blank:]]*[[:digit:]]{4}[-\.,[:blank:]]*[[:digit:]]{4}[-\.,[:blank:]]*[[:digit:]]{4}[-\.,[:blank:]]*(\d{4}|\d{2})';
URL_Escape constant varchar2(100):='\.jpg|\.rar|\.zip|\.png|\.gif|\.pdf|\.doc|\.excel|\.swf|\.mpg|\.\.|\.rmvb';

DUP_VAL_INDEX exception;
pragma exception_init(DUP_VAL_INDEX,-0001);

begin
if article_detail_id_$ is not null and article_detail_id_$<>0 then
Offset_URL:=1;
Offset_Email:=1;
Offset_Phone:=1;
Offset_Account:=1;

while Offset_URL<>0 or Offset_Email<>0 or Offset_Phone<>0 or Offset_Account<>0
loop
--獲取URL
if Offset_URL<>0 then
select trim(to_char(REGEXP_SUBSTR(content_text_$,URL_RegExp, Offset_URL, 1,'i')))
into URL from dual;
--獲取從offset位置開始的第一個符合URL表示式的字串位置,並賦給offset
select REGEXP_INSTR(content_text_$, URL_RegExp, Offset_URL, 1, 1,'i')
into Offset_URL from dual;
end if;
--獲取Email
if Offset_Email<>0 then
select trim(to_char(REGEXP_SUBSTR(content_text_$,Email_RegExp, Offset_Email, 1,'i')))
into Email from dual;
--獲取從offset位置開始的第一個符合Email表示式的字串位置,並賦給offset
select REGEXP_INSTR(content_text_$, Email_RegExp, Offset_Email, 1, 1,'i')
into Offset_Email from dual;
end if;
--獲取Phone
if Offset_Phone<>0 then
select trim(to_char(REGEXP_SUBSTR(content_text_$,Phone_RegExp, Offset_Phone, 1,'i')))
into Phone from dual;
--獲取從offset位置開始的第一個符合Phone表示式的字串位置,並賦給offset
select REGEXP_INSTR(content_text_$, Phone_RegExp, Offset_Phone, 1, 1,'i')
into Offset_Phone from dual;
end if;
--獲取Bank_Account
if Offset_Account<>0 then
select trim(to_char(REGEXP_SUBSTR(content_text_$,Bank_Account_RegExp, Offset_Account, 1,'i')))
into Bank_Account from dual;
--獲取從offset位置開始的第一個符合Phone表示式的字串位置,並賦給offset
select REGEXP_INSTR(content_text_$, Bank_Account_RegExp, Offset_Account, 1, 1,'i')
into Offset_Account from dual;
end if;

--URL插入到陣列中
if (length(URL)>0 and length(URL)<800) and REGEXP_INSTR(URL, URL_Escape, 1, 1, 0, 'i')=0 then
Is_Exsit_Flag :=0; 
FOR I IN 1..URL_Array.COUNT LOOP 
if URL=URL_Array(I) then
Is_Exsit_Flag:=1;
end if;
END LOOP;
--如果陣列中不存在當前值,則插入到陣列
if Is_Exsit_Flag=0 then 
URL_Array.EXTEND(1);
URL_Array(URL_V_Num):=URL;
URL_V_Num:=URL_V_Num+1;
end if;
end if; 
--Email插入到陣列中
if (length(Email)>0 and length(Email)<100) then
Is_Exsit_Flag :=0; 
FOR I IN 1..Email_Array.COUNT LOOP 
if Email=Email_Array(I) then
Is_Exsit_Flag:=1;
end if;
END LOOP;
--如果陣列中不存在當前值,則插入到陣列
if Is_Exsit_Flag=0 then 
Email_Array.EXTEND(1);
Email_Array(Email_V_Num):=Email;
Email_V_Num:=Email_V_Num+1;
end if;
end if; 
--Phone插入到陣列中
if (length(Phone)>6 and length(Phone)<100) then
Is_Exsit_Flag :=0; 
FOR I IN 1..Phone_Array.COUNT LOOP 
if Phone=Phone_Array(I) then
Is_Exsit_Flag:=1;
end if;
END LOOP;
--如果陣列中不存在當前值,則插入到陣列
if Is_Exsit_Flag=0 then 
Phone_Array.EXTEND(1);
Phone_Array(Phone_V_Num):=Phone;
Phone_V_Num:=Phone_V_Num+1;
end if;
end if; 
--Bank_Account插入到陣列中
if (length(Bank_Account)>0 and length(Bank_Account)<100) then
Is_Exsit_Flag :=0; 
FOR I IN 1..Account_Array.COUNT LOOP 
if Bank_Account=Account_Array(I) then
Is_Exsit_Flag:=1;
end if;
END LOOP;
--如果陣列中不存在當前值,則插入到陣列
if Is_Exsit_Flag=0 then 
Account_Array.EXTEND(1);
Account_Array(Account_V_Num):=Bank_Account;
Account_V_Num:=Account_V_Num+1;
end if;
end if; 
end loop;

-- Dbms_Output.put_line('Array is:'||URL_Array(1));

--插入獲取到的URL
FOR I IN 1..URL_Array.COUNT LOOP 
insert into article_data(article_detail_id,article_record_md5_id,data_type,data_is_url,data_value)
values(article_detail_id_$,Record_Md5_ID_$,'URL','1',URL_Array(I));
END LOOP;
--插入獲取到的Email
FOR I IN 1..Email_Array.COUNT LOOP
insert into article_data(article_detail_id,article_record_md5_id,data_type,data_is_url,data_value)
values(article_detail_id_$,Record_Md5_ID_$,'Email','0',Email_Array(I));
END LOOP;
--插入獲取到的Phone
FOR I IN 1..Phone_Array.COUNT LOOP
insert into article_data(article_detail_id,article_record_md5_id,data_type,data_is_url,data_value)
values(article_detail_id_$,Record_Md5_ID_$,'Phone','0',Phone_Array(I));
END LOOP;
--插入獲取到的Bank_Account
FOR I IN 1..Account_Array.COUNT LOOP
insert into article_data(article_detail_id,article_record_md5_id,data_type,data_is_url,data_value)
values(article_detail_id_$,Record_Md5_ID_$,'Bank Account','0',Account_Array(I));
END LOOP;

end if;
Exception
when NO_DATA_FOUND then
ReturnValue:=-1000;
when DUP_VAL_INDEX then
ReturnValue:=-1001;
when VALUE_ERROR then
ReturnValue:=-1002;
when TOO_MANY_ROWS then
ReturnValue:=-1003;
when OTHERS then
ReturnValue:=-1004;
--Dbms_Output.put_line('The SQLCode is: '||SQLCODE);
--Dbms_Output.put_line('The SQLERRM is: '||SQLERRM);
end;
end SP_GET_ARTICLE_DATA;

分類: Oracel

好文要頂 關注我 收藏該文  

Jason_liu
關注 - 1
粉絲 - 19

+加關注

0

0

« 上一篇:XCode6.0的iOS免證書真機測試方法(MAC及黑蘋果均有效)[轉]
» 下一篇:INSERT INTO 語句的語法錯誤【 OLE報錯,office終端執行SQL沒有問題】

posted on 2015-01-26 10:19 Jason_liu 閱讀(800) 評論(0) 編輯 收藏

https://www.cnblogs.com/jason-liu-blogs/p/4249567.html