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]);
陣列是具有相同資料型別的一組成員的集合。每個成員都有一個唯一的下標,它取決於成員在陣列中的位置。在PL/SQL中,陣列資料型別是VARRAY(variable array,即可變陣列)。
定義VARRAY資料型別的語法如下:
TYPE VARRAY_NAMEIS VARRAY(SIZE) OF ELEMENT_TYPE [NOT NULL];
其中,varray_name是VARRAY資料型別的名稱,size是正整數,表示可以容納的成員的最大數量,每個成員的資料型別是element_typeo預設時,成員可以取空值,否則需要使用NOT NULL加以限制。
定義記錄表(或索引表)資料型別。它與記錄型別相似,但它是對記錄型別的擴充套件。它可以處理多行記錄,類似於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 舉例
[sql] view plain copy
- --組織機構結構表
- CREATE TABLE SF_ORG
- (
- ORG_ID INT NOT NULL, --組織機構主鍵ID
- ORG_NAME VARCHAR2(50),--組織機構名稱
- PARENT_ID INT--組織機構的父級
- )
- --一級組織機構
- INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(1, '一級部門1',0);
- --二級部門
- INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(2, '二級部門2',1);
- INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(3, '二級部門3',1);
- INSERT INTO SF_ORG(ORG_ID, ORG_NAME, PARENT_ID) VALUES(4, '二級部門4',1);
先定義一個只與SF_ORG表中某幾個列的資料型別相同的記錄資料型別TYPE_ORG_RECORD,然後宣告一個該資料型別的記錄變數V_ORG_RECORD,最後用替換變數&ORG_ID接受輸入的僱員編碼,查詢並顯示該僱員的這幾列中的資訊。注意,在使用RECORD資料型別的變數時要用“.”運算子指定記錄變數名限定詞。
一個記錄型別的變數只能儲存從資料庫中查詢出的一行記錄,如果查詢出了多行記錄,就會出現錯誤。
[sql] view plain copy
- DECLARE
- TYPE TYPE_ORG_RECORD IS RECORD(
- V_ORG_NAME SF_ORG.ORG_NAME%TYPE,
- V_PARENT_ID SF_ORG.PARENT_ID%TYPE);
- V_ORG_RECORD TYPE_ORG_RECORD;
- BEGIN
- SELECT ORG_NAME,PARENT_ID INTO V_ORG_RECORD
- FROM SF_ORG SO
- WHERE SO.ORG_ID=&ORG_ID;
- DBMS_OUTPUT.PUT_LINE('部門名稱:' || V_ORG_RECORD.V_ORG_NAME);
- DBMS_OUTPUT.PUT_LINE('上級部門編碼:' || TO_CHAR(V_ORG_RECORD.V_PARENT_ID));
- END;
先定義一個能儲存5個VARCHAR2(25)資料型別的成員的VARRAY資料型別ORG_VARRAY_TYPE,然後宣告一個該資料型別的VARRAY變數V_ORG_VARRAY,最後用與ORG_VARRAY_TYPE資料型別同名的建構函式語法給V_ORG_VARRAY變數賦予初值並顯示賦值結果。
注意,在引用陣列中的成員時.需要在一對括號中使用順序下標,下標從1開始而不是從0開始。
[sql] view plain copy
- DECLARE
- TYPE ORG_VARRAY_TYPE IS VARRAY(5) OF VARCHAR2(25);
- V_ORG_VARRAY ORG_VARRAY_TYPE;
- BEGIN
- V_ORG_VARRAY := ORG_VARRAY_TYPE('1','2','3','4','5');
- DBMS_OUTPUT.PUT_LINE('輸出1:' || V_ORG_VARRAY(1) || '、'|| V_ORG_VARRAY(2) || '、'|| V_ORG_VARRAY(3) || '、'|| V_ORG_VARRAY(4));
- DBMS_OUTPUT.PUT_LINE('輸出2:' || V_ORG_VARRAY(5));
- V_ORG_VARRAY(5) := '5001';
- DBMS_OUTPUT.PUT_LINE('輸出3:' || V_ORG_VARRAY(5));
- END;
這個和VARRAY類似。但是賦值方式稍微有點不同,不能使用同名的建構函式進行賦值。具體的如下:
[sql] view plain copy
- DECLARE
- TYPE ORG_TABLE_TYPE IS TABLE OF VARCHAR2(25)
- INDEX BY BINARY_INTEGER;
- V_ORG_TABLE ORG_TABLE_TYPE;
- BEGIN
- V_ORG_TABLE(1) := '1';
- V_ORG_TABLE(2) := '2';
- V_ORG_TABLE(3) := '3';
- V_ORG_TABLE(4) := '4';
- V_ORG_TABLE(5) := '5';
- DBMS_OUTPUT.PUT_LINE('輸出1:' || V_ORG_TABLE(1) || '、'|| V_ORG_TABLE(2) || '、'|| V_ORG_TABLE(3) || '、'|| V_ORG_TABLE(4));
- DBMS_OUTPUT.PUT_LINE('輸出2:' || V_ORG_TABLE(5));
- END;
採用bulkcollect可以將查詢結果一次性地載入到collections中。而不是通過cursor一條一條地處理。
[sql] view plain copy
- DECLARE
- TYPE T_TYPE IS TABLE OF SF_ORG%ROWTYPE;
- V_TYPE T_TYPE;
- BEGIN
- SELECT ORG_ID,ORG_NAME,PARENT_ID BULK COLLECT INTO V_TYPE
- FROM SF_ORG
- WHERE SF_ORG.ORG_ID <= 3;
- FOR V_INDEX IN V_TYPE.FIRST .. V_TYPE.LAST LOOP
- DBMS_OUTPUT.PUT_LINE(V_TYPE(V_INDEX).C1 || ' ' || V_TYPE(V_INDEX).C2);
- END LOOP;
- END;
採用bulkcollect可以將查詢結果一次性地載入到collections中。而不是通過cursor一條一條地處理。
[sql] view plain copy
- DECLARE
- TYPE TEST_EMP IS RECORD
- (
- C1 SF_ORG.ORG_NAME%TYPE,
- C2 SF_ORG.PARENT_ID%TYPE
- );
- TYPE T_TYPE IS TABLE OF TEST_EMP;
- V_TYPE T_TYPE;
- BEGIN
- SELECT ORG_NAME, PARENT_ID BULK COLLECT INTO V_TYPE
- FROM SF_ORG
- WHERE SF_ORG.ORG_ID <= 3;
- FOR V_INDEX IN V_TYPE.FIRST .. V_TYPE.LAST LOOP
- DBMS_OUTPUT.PUT_LINE(V_TYPE(V_INDEX).C1 || ' ' || V_TYPE(V_INDEX).C2);
- END LOOP;
- 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
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