日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle存储过程快速入门

發布時間:2025/3/15 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle存储过程快速入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.什么是oracle存儲過程

存儲過程和函數也是一種PL/SQL塊,是存入數據庫的PL/SQL塊。但存儲過程和函數不同于已經介紹過的PL/SQL程序,我們通常把PL/SQL程序稱為無名塊,而存儲過程和函數是以命名的方式存儲于數據庫中的。和PL/SQL程序相比,存儲過程有很多優點,具體歸納:

1. 存儲過程和函數以命名的數據庫對象形式存儲于數據庫當中。存儲在數據庫中的優點是很明顯的,因為代碼不保存在本地,用戶可以在任何客戶機上登錄到數據庫,并調用或修改代碼。

2. 存儲過程和函數可由數據庫提供安全保證,要想使用存儲過程和函數,需要有存儲過程和函數的所有者的授權,只有被授權的用戶或創建者本身才能執行存儲過程或調用函數。

3. 存儲過程和函數的信息是寫入數據字典的,所以存儲過程可以看作是一個公用模塊,用戶編寫的PL/SQL程序或其他存儲過程都可以調用它(但存儲過程和函數不能調用PL/SQL程序)。一個重復使用的功能,可以設計成為存儲過程。

4. 像其他高級語言的過程和函數一樣,可以傳遞參數給存儲過程或函數,參數的傳遞也有多種方式。存儲過程可以有返回值,也可以沒有返回值,存儲過程的返回值必須通過參數帶回;函數有一定的數據類型,像其他的標準函數一樣,我們可以通過對函數名的調用返回函數值。

5. 存儲過程和函數需要進行編譯,以排除語法錯誤,只有編譯通過才能調用。

2.如何創建和刪除存儲過程

2.1.創建存儲過程的語法

CREATE [OR REPLACE] PROCEDURE 存儲過程名[(參數[IN|OUT|IN OUT] 數據類型...)]

{AS|IS}

[說明部分]

BEGIN

可執行部分

[EXCEPTION

錯誤處理部分]

END [過程名];

其中:

可選關鍵字OR REPLACE 表示如果存儲過程已經存在,則用新的存儲過程覆蓋,通常用于存儲過程的重建。

參數部分用于定義多個參數(如果沒有參數,就可以省略)。參數有三種形式:IN、OUT和IN OUT。如果沒有指明參數的形式,則默認為IN。 關鍵字AS也可以寫成IS,后跟過程的說明部分,可以在此定義過程的局部變量。(注意:大小寫不敏感)。

簡單的存儲過程示例:

create or replace procedure hello_world as

say_hi varchar2(20);

begin

say_hi := 'Hello World!';

dbms_output.put_line(say_hi);

end;

2.2 刪除存儲過程

語法:

DROP PROCEDURE 存儲過程名;

如:drop procedure hello_world;

3.存儲過程的查看

可以通過對數據字典的訪問來查詢存儲過程或函數的有關信息,如果要查詢當前用戶的存儲過程或函數的源代碼,可以通過對USER_SOURCE數據字典視圖的查詢得到。

3.1查看存儲過程的腳本

如查詢存儲過程hello_world的腳本

Select text from user_source where name = ‘HELLO_WORLD’;

(這里的過程名必須大寫)

3.2 查看存儲過程的狀態

如:select status from user_objects where object_name = ‘HELLO_WORLD’;

說明:VALID表示該存儲過程有效(即通過編譯),INVALID表示存儲過程無效或需要重新編譯。當Oracle調用一個無效的存儲過程或函數時,首先試圖對其進行編譯,如果編譯成功則將狀態置成VALID并執行,否則給出錯誤信息。

當一個存儲過程編譯成功,狀態變為VALID,會不會在某些情況下變成INVALID。結論是完全可能的。比如一個存儲過程中包含對表的查詢,如果表被修改或刪除,存儲過程就會變成無效INVALID。所以要注意存儲過程和函數對其他對象的依賴關系。

4.存儲過程參數說明

三種形式的參數

1. IN 定義一個輸入參數變量,用于傳遞參數給存儲過程

2. OUT 定義一個輸出參數變量,用于從存儲過程獲取數據

3. IN OUT 定義一個輸入、輸出參數變量,兼有以上兩者的功能

參數的定義形式和作用如下:

4.1 IN參數

語法:參數名 IN 數據類型 DEFAULT 值;

定義一個輸入參數變量,用于傳遞參數給存儲過程。在調用存儲過程時,主程序的實際參數可以是常量、有值變量或表達式等。DEFAULT 關鍵字為可選項,用來設定參數的默認值。如果在調用存儲過程時不指明參數,則參數變量取默認值。在存儲過程中,輸入變量接收主程序傳遞的值,但不能對其進行賦值。

4.2 OUT參數

語法:參數名 OUT 數據類型;

定義一個輸出參數變量,用于從存儲過程獲取數據,即變量從存儲過程中返回值給主程序。

在調用存儲過程時,主程序的實際參數只能是一個變量,而不能是常量或表達式。在存儲過程中,參數變量只能被賦值而不能將其用于賦值,在存儲過程中必須給輸出變量至少賦值一次。

4.3 IN OUT參數

語法:參數名 IN OUT 數據類型 DEFAULT 值;

定義一個輸入、輸出參數變量,兼有以上兩者的功能。在調用存儲過程時,主程序的實際參數只能是一個變量,而不能是常量或表達式。DEFAULT 關鍵字為可選項,用來設定參數的默認值。在存儲過程中,變量接收主程序傳遞的值,同時可以參加賦值運算,也可以對其進行賦值。在存儲過程中必須給變量至少賦值一次。

示例:

create or replace procedure say_hi(to_whom in varchar2 default '張三', who out varchar2)

as

who_name varchar(20);

begin

who_name := '李四';

who := who_name;

dbms_output.put_line('Say Hi to '||to_whom);

end;

create or replace procedure invoke_say_hi

as

who varchar2(20);

whom varchar2(20);

begin

whom := '小明';

say_hi(whom, who);

say_hi(who => who);

dbms_output.put_line(who||'say hi to '||whom);

end;

參數的值由調用者傳遞,傳遞的參數的個數、類型和順序應該和定義的一致。如果順序不一致,可以采用以下調用方法:

過程名(參數名 => 參數的值,參數名 => 參數的值, ~~~~~);

如上面的示例: say_hi(who => who); =>運算符左側是參數名,右側是參數表達式.

存儲過程參數寬度:

無法在存儲過程的定義中指定存儲參數的寬度,也就導致了我們無法在存儲過程中控制傳入變量的寬度。這個寬度是完全由外部傳入時決定的。

5.游標

5.1 普通游標

游標定義: cursor [游標名] is [sql語句]

普通游標把整個查詢已經寫死,調用時不可以作任何改變

注意:這里的is不能用as代替

示例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

create or replace procedure cursor_sample

?

as

?

user_name varchar2(20);

?

user_id varchar2(20);

?

cursor select_user is select t.user_name, t.user_id from t_user t;

?

begin

?

open select_user;

?

loop

?

fetch select_user into user_name, user_id;

?

exit when select_user%notfound;

?

dbms_output.put_line('UserId:'||user_id||' UserName: '||user_name);

?

end loop;

?

close select_user;

?

end;

5.2動態查詢游標

動態查詢游標,查詢條件的參數由變量決定。

例:

create or replace procedure cursor_sample2

as

vuser_id varchar2(20);

vuser_name varchar2(20);

cursor get_user_by_id is select t.user_id, t.user_name from t_user t where t.user_id = vuser_id;

begin

vuser_id := 'root2';

open get_user_by_id;

loop

fetch get_user_by_id into vuser_id, vuser_name;

exit when get_user_by_id%notfound;

dbms_output.put_line('UserName:'||vuser_name||' UserId:'||vuser_id);

end loop;

close get_user_by_id;

end;

5.3游標變量

先定義了一個引用游標類型,然后再聲明了一個游標變量. 然后再用open for 來打開一個查詢。需要注意的是它可以多次使用,用來打開不同的查詢。

示例:

create or replace procedure cursor_sample3

as

vuser_name varchar2(20);

vuser_id varchar2(20);

type cursor_type is ref cursor;

select_user cursor_type;

begin

open select_user for select t.user_name, t.user_id from t_user t;

loop

fetch select_user into vuser_name, vuser_id;

exit when select_user%notfound;

dbms_output.put_line('UserName:'||vuser_name||' ||UserId:'||vuser_id);

end loop;

close select_user;

dbms_output.put_line('***********************************************');

dbms_output.put_line('****************第二次使用游標**********************');

open select_user for select t.user_name, t.user_id from t_user t where t.user_id = 'root2';

loop

fetch select_user into vuser_name, vuser_id;

exit when select_user%notfound;

dbms_output.put_line('UserName:'||vuser_name||' ||UserId:'||vuser_id);

end loop;

close select_user;

end;

5.4游標循環的方法

(1)游標的%found和%notfound屬性。

能從游標中取出記錄,得到的結果為%found,取不到記錄為%notfound。在打開一個游標之后,馬上檢查它的%found或%notfound屬性,它得到的結果即不是true也不是false.而是null.必須執行一條fetch語句后,這些屬性才有值。

三種循環方法

5.4.1【Loop循環】

loop

fetch select_user into vuser_name, vuser_id;

exit when select_user%notfound;

【Do something】;

end loop;

close select_user;

5.4.2【while循環】

fetch select_user into vuser_name, vuser_id;

while select_user%found loop

dbms_output.put_line('UserName:'||vuser_name||' ||UserId:'||vuser_id);

fetch select_user into vuser_name, vuser_id;

end loop;

close select_user;

說明:我們知道了一個游標打開后,必須執行一次fetch語句,游標的屬性才會起作用。所以使用while 循環時,就需要在循環之前進行一次fetch動作。

而且數據處理動作必須放在循環體內的fetch方法之前。循環體內的fetch方法要放在最后。否則就會多處理一次。這一點也要非常的小心。

使用while來循環處理游標是最復雜的方法。

5.4.3【for循環】

create or replace procedure cursor_sample4

as

vuser_name varchar2(20);

vuser_id varchar2(20);

cursor select_user is select t.user_name, t.user_id from t_user t;

begin

for v_pos in select_user loop

vuser_name := v_pos.user_name;

vuser_id := v_pos.user_id;

dbms_output.put_line('UserName:'||vuser_name||'UserId'||vuser_id);

end loop;

end;

說明:for循環是比較簡單實用的方法。

首先,它會自動open和close游標。解決了你忘記打開或關閉游標的煩惱。

其次,自動定義了一個記錄類型及聲明該類型的變量,并自動fetch數據到這個變量中。 我們需要注意v_pos 這個變量無需要在循環外進行聲明,無需要為其指定數據類型。 它應該是一個記錄類型,具體的結構是由游標決定的。這個變量的作用域僅僅是在循環體內。 把v_pos看作一個記錄變量就可以了,如果要獲得某一個值就像調用記錄一樣就可以了。 如v_pos.user_name由此可見,for循環是用來循環游標的最好方法。高效,簡潔,安全。

6.異常處理

語法:exception when [異常名] then [dosomething] …

When others then [dosomething];

示例:

create or replace procedure exception_sample

as

vuser_name varchar2(20);

vuser_id varchar2(20);

vsqlcode varchar2(10);

vsqlerrm varchar2(1000);

begin

select t.user_name, t.user_id into vuser_name, vuser_id from t_user t where 1 = 0;

exception

when others

then

vsqlcode := sqlcode;

vsqlerrm := sqlerrm;

dbms_output.put_line('Exception, code:'||vsqlcode||' Error message:'||sqlerrm);

end;

另外:若在代碼中需要拋出異常時,用raise+異常名

如以下例子:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

create or replace procedure exception_sample2

?

as

?

vuser_name varchar2(20);

?

vuser_id varchar2(20);

?

yourexception exception; --自定義異常

?

cursor select_user is select t.user_name, t.user_id from t_user t;

?

begin

?

open select_user;

?

loop

?

fetch select_user into vuser_name, vuser_id;

?

exit when select_user%notfound;

?

if vuser_id = 'root2' then

?

raise yourexception; --拋出異常

?

end if;

?

end loop;

?

exception

?

when yourexception then

?

dbms_output.put_line('人品異常');

?

when others then

?

dbms_output.put_line(sqlcode||sqlerrm);

?

end;

已經命名的異常

命名的系統異常 產生原因

ACCESS_INTO_NULL 未定義對象

CASE_NOT_FOUND CASE 中若未包含相應的 WHEN ,并且沒有設置

ELSE 時

COLLECTION_IS_NULL 集合元素未初始化

CURSER_ALREADY_OPEN 游標已經打開

DUP_VAL_ON_INDEX 唯一索引對應的列上有重復的值

INVALID_CURSOR 在不合法的游標上進行操作

INVALID_NUMBER 內嵌的 SQL 語句不能將字符轉換為數字

NO_DATA_FOUND 使用 select into 未返回行,或應用索引表未初始化的

TOO_MANY_ROWS 執行 select into 時,結果集超過一行

ZERO_DIVIDE 除數為 0

SUBSCRIPT_BEYOND_COUNT 元素下標超過嵌套表或 VARRAY 的最大值

SUBSCRIPT_OUTSIDE_LIMIT 使用嵌套表或 VARRAY 時,將下標指定為負數

VALUE_ERROR 賦值時,變量長度不足以容納實際數據

LOGIN_DENIED PL/SQL 應用程序連接到 oracle 數據庫時,提供了不

正確的用戶名或密碼

NOT_LOGGED_ON PL/SQL 應用程序在沒有連接 oralce 數據庫的情況下

訪問數據

PROGRAM_ERROR PL/SQL 內部問題,可能需要重裝數據字典& pl./SQL

系統包

ROWTYPE_MISMATCH 宿主游標變量與 PL/SQL 游標變量的返回類型不兼容

SELF_IS_NULL 使用對象類型時,在 null 對象上調用對象方法

STORAGE_ERROR 運行 PL/SQL 時,超出內存空間

SYS_INVALID_ID 無效的 ROWID 字符串

TIMEOUT_ON_RESOURCE Oracle 在等待資源時超時

7.過程內部塊

我們知道了存儲過程的結構,語句塊由begin開始,以end結束。這些塊是可以嵌套。在語句塊中可以嵌套任何以下的塊:

Declare … begin … exception … end;

例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

create or replace procedure innerblock_sample

?

as

?

vuser_name varchar2(20);

?

vuser_id varchar2(20);

?

cursor select_user is select t.user_name, t.user_id from t_user t;

?

begin

?

open select_user;

?

loop

?

fetch select_user into vuser_name, vuser_id;

?

exit when select_user%notfound;

?

dbms_output.put_line('UserName:'||vuser_name||'UserId'||vuser_id);

?

end loop;

?

close select_user;

?

declare

?

vuser_level varchar2(20);

?

cursor get_level is select t.user_level from t_user t;

?

begin

?

open get_level;

?

loop

?

fetch get_level into vuser_level;

?

exit when get_level%notfound;

?

dbms_output.put_line('UserLevel:'||vuser_level);

?

end loop;

?

close get_level;

?

exception when others then

?

dbms_output.put_line(sqlcode||sqlerrm);

?

end;

?

exception when others then

?

dbms_output.put_line(sqlcode||sqlerrm);

?

end;

總結

以上是生活随笔為你收集整理的Oracle存储过程快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久久国产亚洲 | 欧美乱妇18p | 日韩中文欧美 | 中文字幕第十一页 | 欧美国产日韩在线观看成人 | 日韩少妇内射免费播放 | 午夜电影一区二区三区 | 大片av | 印度午夜性春猛xxx交 | 99视频网址 | 91看片免费版 | 日韩亚洲在线 | 久久久久久穴 | 久久婷婷五月综合色国产香蕉 | av第一区| 在线视频亚洲色图 | 久久天堂av综合合色蜜桃网 | 毛片中文字幕 | 超碰青草 | 少妇粉嫩小泬喷水视频www | 天堂在线视频tv | 免费黄色网页 | 免费在线观看av的网站 | 永久国产 | 亚洲天码中字 | a一级免费视频 | 日韩成人一区二区三区 | 九一亚色| 国产经典毛片 | 极品久久久久久 | 国产精品高潮呻吟久久aⅴ码 | 国产伦视频| 七仙女欲春2一级裸体片 | 最近中文字幕一区二区 | 亚洲精品一区二区三区蜜臀 | 色哟哟在线播放 | 黄色a一级 | 午夜看片在线 | 日本不卡一 | 一区二区精品视频在线观看 | 中文字幕视频一区二区 | 素人一区| 国产天堂久久 | 日韩一区二区三区不卡视频 | 亚洲一区 在线播放 | 欧美日韩一区二区三区69堂 | 精品无码久久久久国产 | 欧美婷婷精品激情 | 久久极品视频 | 日本视频久久 | 超碰8| 亚洲图片欧美在线看 | 四虎永久在线观看 | 成人手机视频在线观看 | 免费裸体视频网站 | 日韩av手机在线观看 | 亚洲AV第二区国产精品 | 日韩在线高清视频 | 国产偷怕 | 亚洲国产爱 | 动漫毛片 | 欧美一区二区高清视频 | 黄色午夜网站 | 永久免费在线播放 | 国产精品福利导航 | 欧美不在线 | 青青国产视频 | 91看片淫黄大片91桃色 | 亚洲欧美小视频 | 欧美激情91| avtt亚洲天堂 | 欧美日韩色综合 | 亚洲日本在线播放 | 国产精品爽爽爽 | 午夜成人鲁丝片午夜精品 | 国产免费一区二区三区四区五区 | 99亚洲精品| 亚洲少妇中文字幕 | 久久在线免费 | 国产伦精品一区二区三区照片91 | 最新国产在线视频 | 伊人五月婷婷 | 狠狠爱免费视频 | 欧美午夜视频在线观看 | 中文字幕蜜桃 | 黄色免费视频网站 | 亚洲国产剧情在线观看 | 在线你懂的视频 | 夜色视频在线观看 | 国产精品11| 亚洲在线第一页 | 日本精品视频在线观看 | 亚洲第一二三四区 | 亚洲精选中文字幕 | 国产美女久久久 | 国产精品免费无码 | 日韩中文字幕一区二区三区四区 | 久久噜噜色综合一区二区 | 嫩草影院久久 |