存儲過程學習1- 無參存儲過程
1 存儲過程定義:
一組為了完成特定功能的 PL/SQL 語句集,存儲在數據庫中,
經過第一次編譯后再次調用不需要再次編譯,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。
存儲過程是數據庫中的一個重要對象。
2 存儲過程優點:
- 可維護性高
2)簡化操作流程
3 存儲過程缺點
1)數據庫移植不方便
4 hello world
create or replace procedure pro_test_demo
iS
begin
dbms_output.put_line('hello world')
end;
創建存儲過程,進行編譯,編譯成功后會在Procedure看到結果。
5 運行存儲過程
begin
pro_test_demo;
end;
存儲過程學習2-有參存儲過程
1 定義
create or replace procedure pro_with_params(v_a integer, v_b varchar2(36))
is
begin
dbms_output.put_line('第一個參數是:' || v_a);
end;
-- 和c類似, 參數類型寫在后面
2 執行
begin
execute pro_with_params(1, 'abd');
end;
存儲過程學習3-有輸出參數的存儲過程
1 定義
create or replace procedure pro_with_out_params(v_in_a in integer, v_out_b out varchar2)
is
begin
b:= 'abdd';
dbms_output.put_line('輸入參數:' || a);
end;
2 執行
declare i varchar2(36);
begin
pro_with_out_params(1, i);
dbms_output.put_line('輸出參數:' || i);
end;
注:存儲過程括弧里面定義varchar時不需要長度,但在declare定義時必須要有長度。
存儲過程學習4-存儲過程變量%TYPE
1 存儲過程中的變量類型:
1)標量類型
2)復合類型:記錄類型,索引表類型(關聯數組), varry變長數組
2 標量類型
常用的:NUMBER、CHAR 、VARCHAR2 、VARCHAR、NCHAR 、NVARCHAR2 、LONG 、DATE 、TIMESTAMP
3 %TYPE
%TYPE這種定義方式的變量類型, 利用已經存在的數據類型來定義新數據的數據類型,如定義多個變量或常量時,主要前面使用過的數據類型,后面的變量
可以利用%TYPE引用。
sex LY_DS.LY_NB%TYPE, 表示:定義一個變量sex, 它的數據類型與表LY_DS中的字段LY_NB類型一致
create or replace procedure test_select_procedure(
project PCA_PROJECT.NAME%TYPE, countNum out number)
is
begin
select count(*) into countNum from pca_project where name=project_name;
end;
存儲過程學習5 -- 記錄類型 %ROWTYPE
有一種場景:select多列,除了使用into的方法,還有另外一種引用名稱.引用成員
先來into的寫法
select count(*), max(id) into countNum, maxId from pca_project where id= 'ad';
如果是要獲取多列的結果呢,into不合適。記錄類型就是解決這個問題的。
1)type的聲明方法
格式:type type_name is recored(col_name, col_type);
括號可多列,以逗號隔開。
declare
TYPE new_type IS RECORD -- 這是聲明一種變量類型
(
v_project_name PCA_PROJECT.PROJECT_NAME%TYPE,
v_project_id PCA_PROJECT.PROJECT_ID%TYPE
);
v_obj new_type; -- 使用這種變量類型聲明一個變量v_obj
BEGIN
select project_name, project_id into v_obj from pca_project where id='ss';
END;
2 %ROWTYPE的聲明方法
%ROWTYPE, 該類型是提取行記錄時常用的存儲數據的方式。優點都是,避免表中字段數據類型改變,導致pl/sql塊出錯。
declare
v_obj pca_project%ROWTYPE;
BEGIN
select * into v_obj from pca_project where id='sdf';
dbms_output.put_line('第一個變量' || v_obj.name);
dbms_output.put_line('第二個變量' || v_obj.id);
END;
into前邊最好為*, 否則就要將所有字段寫全。
存儲過程學習6-關聯數組(索引表類型)
與數組類型,關聯數組利用鍵值查找對應的數據。不同是,鍵值和數組的下標只為整數不一樣,鍵值可為字符串。
1type自定義類型
1) 聲明一個存儲pca_project整行數據的索引表,下標為數字(binary_integer)
type index_row_type is table of pca_project%TYPE index by binary_integer;
2) 聲明一個存儲字符串數據的索引表,下標為數字
type index_varchar_type is table of varchar2(36) index by binary_integer;
3) 聲明一個存儲字符串數據的索引表,下標為字符串
type index_str_type is table of varchar(100) index by varchar(10);
2 利用自定義的索引表,定義變量
1) 聲明一個下標為數字, 值為pca_project整行數據的變量
v_row index_row_type;
2) 聲明一個下標為數字, 值為字符串的變量
v_var index_varchar_type;
3) 聲明一個下標為字符串,值為字符串的變量
v_str_val index_str_type;
3 索引表賦值
和字典一樣
- select * into v_row(1) from pca_project where id ='1';
- v_var(1) := '正數'; v_var(-1) := '負數'
- v_str_val('liuzhipeng') := '100分';
存儲過程學習7-變長數組
1)聲明
type array_type is varray(100) of varchar(100);
聲明一個最多容納100個元素的數組,每個元素類型為varchar(100), 下標從1開始,不是0;
- 定義變量
v_array array_type := array_type('one', 'two');
v_array2 array_type := array_type();
v_array2 array_type := array_type();
3) 獲取第一個元素
v_array(1)
4)為數組擴展下一個空位
v_array2.extend;
v_array2(1) := 'hello';
v_array2.extend;
v_array2(2) := 'world';
- 為數組初始化長度
v_array3.extend(v_array2.count());
v_array3.extend(4);
存儲過程學習8-簡單增刪改查sql
1 調用存儲過程的方法
1) begin end內
begin
pro_test_demo;
pro_with_params(1);
end;
2)execute執行
execute pro_test_demo;
execute pro_with_params(1);
- call
call pro_test_demo;
call pro_with_out_params(1);
2 查詢
create or replace procedure test_select2_procedure
(sex varchar)
AS
countNum number(10); --別忘了寫上具體的長度,並且以分號結束
maxId number(10); --別忘了寫上具體的長度,並且以分號結束
BEGIN
select count(*),max(id) into countNum,maxId from ly_ds where LY_NB=sex;
dbms_output.put_line(countNum);
dbms_output.put_line(maxId);
END;
3 插入 insert into
create or replace procedure test_add_procedure
(id varchar,createtime varchar,name varchar,
age varchar,sex varchar)
AS
BEGIN
insert into ly_ds values(id,createtime,name,age,sex);
commit; --別忘了加提交
end;
4 update
create or replace procedure test_update_procedure
(dsId varchar,mc varchar)
AS
BEGIN
update ly_ds set ly_mc = mc where id = dsId ;
commit; --別忘了加提交
end;
存儲過程學習-9 游標cursor
當查詢返回多條記錄時,需要循環,就要使用到cursor。
1 cursor定義
游標就像查詢數據返回的集合類型,比如List,把它當做一個引用類型,指向內存中查詢結果集。
2 cursor例子
create or replace procedure pro_with_cursor(v_name varchar2)
is
CURSOR test_cursor is select id, name, type from pca_project where name=v_name;
v_cursor test_cursor%ROWTYPE; -- 因為select出來是行記錄,可以使用%ROWTYPE, v_cursor表示一行記錄的對象
BEGIN
for v_cursor in test_cursor loop
exit when test_cursor%notfound;
dbms_output.putline('數據是:' || v_cursor.id ||''||v_cursor.name ||''||v_cursor.type);
end loop;
END;
注意到:游標的操作步驟:聲明游標,打開游標,提取數據,結束游標。但loop循環沒有顯示打開游標和關閉游標。
存儲過程學習-10 遍歷游標的方法for fetch while
create or replace procedure myprocedure is
CURSOR CUR_TEST IS --聲明顯式游標
SELECT ECODE,ENAME
FROM EMP;
CUR CUR_TEST%ROWTYPE; --定義游標變量,該變量的類型為基於游標C_EMP的記錄
BEGIN
--For 循環
FOR CUR IN CUR_TEST LOOP
--循環體
DBMS_OUTPUT.PUT_LINE('員工編號:'||CUR.ECODE ||'員工姓名:'|| CUR.ENAME);
END LOOP;
--Fetch 循環
OPEN CUR_TEST;--必須要明確的打開和關閉游標
LOOP
FETCH CUR_TEST INTO CUR;
EXIT WHEN CUR_TEST%NOTFOUND;
--循環體
DBMS_OUTPUT.PUT_LINE('員工編號:'||CUR.ECODE ||'員工姓名:'|| CUR.ENAME);
END LOOP;
CLOSE C_EMP;
--While 循環
OPEN CUR_TEST;--必須要明確的打開和關閉游標
FETCH CUR_TEST INTO CUR;
WHILE CUR_TEST%FOUND LOOP
--循環體
DBMS_OUTPUT.PUT_LINE('員工編號:'||CUR.ECODE ||'員工姓名:'|| CUR.ENAME);
FETCH CUR_TEST INTO CUR;
END LOOP;
CLOSE C_EMP;
END myprocedure;
從代碼中可以很明顯的看出:
1 使用for循環不需要關注游標是否打開或關閉。
2 for循環會自動將數據fetch到記錄型變量。
3 for循環不需要關注何時要退出,也就是不需要寫退出滿足條件。遍歷完成就會退出。
存儲過程學習11-賦值、相等、分支
1 賦值
i := 0
2 相等
i=0 不相等<>
3 分支
if(條件1) then ... elsif(條件2)then ... else... end if
4 例子
create or replace procedure test_select5_procedure
(innum number,outnum out number)
AS
BEGIN
if (innum > 5) then --(判斷條件是否大於5 ,滿足條件則以then標識進入當前分支)
if(innum = 10) then -- (= 為相等)
outnum := 20; -- (:= 表示賦值)
else
outnum := innum + 1 ;
end if; --- (每個分支的結束都以 end if;來結束)
dbms_output.put_line('第一個分支:'||outnum);
elsif (innum > 0) then --- (elsif 的寫法注意,親測必須這么寫才行,寫成else if不行的)
outnum := innum - 1 ;
dbms_output.put_line('第二個分支:'||outnum);
else
outnum := -1 ;
dbms_output.put_line('第三個分支:'||outnum);
end if; --- (每個分支的結束都以 end if;來結束)
END;
存儲過程學習11-case
create or replace procedure test_case_procedure(idnum varchar)
as
v_project pca_project%rowtype;
begin
select * into v_project from pca_project where id=idnum;
case v_project.sex
when '女' then
dbms_output.put_line('女人');
when '男' then
dbms_output.put_line('男人');
else
dbms_output.put_line('人妖');
end case;
end;