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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Oracle存储过程+游标

發布時間:2023/12/15 综合教程 32 生活家
生活随笔 收集整理的這篇文章主要介紹了 Oracle存储过程+游标 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一. 游標

PL/SQL 是用游標來管理 SQL 的 SELECT 語句的 . 游標是為了處理這些語句而分配的一大塊內存 . 它提供了對一個結果集進行逐行處理的能力 , 可看作是一種特殊的指針 . 它與某個查詢結果集相關聯 , 可以指向結果集的任意位置 , 以便對指定位置的數據進行處理 . 使用它可以在查詢數據的同時對數據進行處理.

二. 游標的屬性

1.%FOUND:判斷當前游標是否正確的指向第一行記錄,如果是則返回true,不是則返回false。

2.%NOTFOUND:與%FOUND相反

3.%ISOPEN:判斷游標是否打開,如果是的話,就返回true,不是則返回false.

4.%ROWCOUNT:判斷當前游標在所指向的結果集中的提取的行數,不是所有的記錄數.

SQL%FOUND和SQL%NOTFOUND
在執行任何DML語句前SQL%FOUND和SQL%NOTFOUND的值都是NULL,在執行DML語句后,SQL%FOUND的屬性值將是:

.TRUE:INSERT
.TRUE:DELETE和UPDATE,至少有一行被DELETE或UPDATE.
. TRUE:SELECTINTO至少返回一行
當SQL%FOUND為TRUE時,SQL%NOTFOUND為FALSE。

另外,有兩個變量屬性

1.%TYPE:聲明變量的類型與表中的某列的數據類型完全一致.

它的好處有:一.是你不必知道某列的確切數據類型.二:當某列的數據類型改變時不用修改變量的數據類型.

不但列名可以使用%TYPE,而且變量、游標、記錄,或聲明的常量都可以使用%TYPE.

2.%ROWTYPE:聲明變量的數據類型與表中的行記錄數據類型一致. 對于自定義的記錄, 則必須聲明自己的域.

三.游標的類型

1.靜態游標

靜態游標只是數據的一個快照,用戶對記錄所做的修改,增加或刪除記錄都不會反映到記錄集中。靜態游標 從不檢測其他的更新、刪除和插入情況。例如,一個靜態游標提取了一行,然后另一個應用程序更新了這一行。如果應用程序從該靜態游標再提取該行,它所看到的值并不發生改變,盡管另一個應用程序已經更改了這行的值。

靜態游標又分為兩種類型

① 顯式游標

顯式游標由用戶定義, 并由用戶來管理游標, 可返回多行記錄.

語法:

declare

Cursor cur(游標名) is select * from myuser;(sql語句);

begin

open cur --打開游標

Fetch cur into [變量名或其他數據類型];

close cur --關閉游標

end;

使用顯式游標一般按照如下規則

聲明游標--打開游標--讀取數據--關閉游標

注:FOR.. IN .. LOOP 語句已經包含OPEN,FETCH,CLOSE操作。所以除外。

例子1:

declare

no myuser.userid%TYPE ;

newuser myuser%ROWTYPE;

Cursor mycursor is select * from myuser;

begin

open mycursor;

loop

fetch mycursor into newuser; --fetch之后將移到下一行數據。

no :=newuser.userid;

if mycursor%NOTFOUND then --這個要放在fetch語句之后,不然會死循環

beginexit;end ;end if;

Dbms_Output.put_line(no);

end loop;

close mycursor;

end;

這是按照規則進行的步驟,下面用另一種方法for。。。in。。。loop。

例子2: for .... in .... loop 演示

declare

Cursor mycursor is select * from myuser;

begin

for newuser in mycursor loop -- 將每條記錄放到newuser 中

begin

Dbms_Output.put_line('UserName is '||newuser.username);

end;

end loop;

end;

例子3:利用帶參數的存儲過程演示

create or replace procedure myproc (username in myuser.username%TYPE)

as

userId myuser.userid%TYPE;

Cursor mycursor is select userid from myuser where username = username;

begin

open mycursor;

fetch mycursor into userId;--先獲取一行數據,游標將移到下一行

while mycursor%FOUND --此時這邊返回的才不是null,不會產生死循環

loop

Dbms_Output.put_line(username||'s userId is '||userId);

fetch mycursor into userId; --如果返回的是多個參數,則在userid后用逗號隔開加入。

end loop;

close mycursor;--關閉游標

end myproc;

例子4:帶參數的游標

declare
Cursor mycursor(username myuser.username%TYPE) is
select userId from myuser where username=username;
usId myuser.userid%TYPE;
begin
open mycursor('xiaomin'); --調用游標要給其參數
loop
fetch mycursor into usId;
exit when mycursor%NOTFOUND;-----當數據完成之后跳出循環
Dbms_Output.put_line('id is '||usId);
end loop;\

close mycursor;
end;

例子5. 游標for循環使用查詢

begin

for newuser in (select username from myuser) loop

begin

Dbms_Output.put_line('userName is ' || newuser.username);

end;

end loop;

end;

例子6. 游標中的子查詢

CURSORC1ISSELECT*FROMempWHERE deptno NOT IN (SELECT deptno FROM dept) WHERE dname! = 'ACCOUNTING');
可以看出與SQL中的子查詢沒有什么區別

②隱式游標

隱式游標的特點:

-隱式游標是由PL/SQL 來管理的, 即不需要聲明游標語句, 也不需要OPEN,FETCH,CLOSE 操作

-隱式游標中必須要有select cur_name into [ 變量名或其他數據類型]. 此句完成OPEN,FETCH,CLOSE 操作.

-隱式游標只能返回一行記錄, 如果無符合條件的記錄將會出現NO_DATA_FOUND 異常. 如果出現多條記錄將出現TOO_MANY_ROWS 異常.

-隱式游標只能用SQL% 判斷其游標屬性

-對于任何位置使用SQL%ISOPEN 結果都是FALSE, 隱式游標由PL/SQL 管理 對于隱式游標而言SQL%ISOPEN總是FALSE,這是因為隱式游標在DML語句執行時打開,結束時就立即關閉

-對于在隱式游標位置前使用SQL%FOUND 或SQL%NOTFOUND, SQL%ROWCOUNT 結果值是NULL( 不確定值)

例子:驗證隱式游標的屬性

declare
uname myuser.username%TYPE;
upass myuser.userpass%TYPE;
userid myuser.userid%TYPE;

begin

if sql%isopen then
-- 判斷游標是否打開

dbms_output.put_line('游標處于開啟狀態');

else

dbms_output.put_line('游標處于關閉狀態');

end if;
if sql%notfound then
-- 判斷游標是否指向有效的行

dbms_output.put_line('游標沒有指向有效行');

else

dbms_output.put_line('游標指向有效行');

end if;

dbms_output.put_line(sql%rowcount);

dbms_output.put_line('---------------');

/** 去掉where 條件時, 將會出現too_many_rows 異常**/

select userid, username, userpass
into userid, uname, upass
from myuser
where userid = 1; -- 隱式游標必-- 須使用INTO

dbms_output.put_line(sql%rowcount);

if sql%isopen then
-- 判斷游標是否打開

dbms_output.put_line('游標處于開啟狀態');

else

dbms_output.put_line('游標處于關閉狀態');

end if;
if sql%notfound then
-- 判斷游標是否指向有效的行

dbms_output.put_line('游標沒有指向有效行');

else

dbms_output.put_line('游標指向有效行');

end if;

exception

when no_data_found then

dbms_output.put_line('no value');

when too_many_rows then

dbms_output.put_line('too many rows');

end;

輸出結果為:

游標處于關閉狀態
游標指向有效行

---------------
1
游標處于關閉狀態
游標指向有效行

二.動態游標

首先 , 游標變量和游標是兩個不同的概念 . 與游標相似 , 游標變量是指向多行查游標詢的結果集的當前行,游標是靜態的 , 游標變量是動態的 ,. 同時游標變量并不參與與特定的查詢綁定,可以修改查詢的sql語句, 所以可以為任何兼容的查詢打開游標變量 , 從而提高靈活性 . 而且 , 還可以將新的值賦予游標變量 , 將它作為參數傳遞給本地和存儲過程 . 游標變量針對每個 PL/SQL 用戶都是可用的 , 可以在客戶端完全使用游標變量 .ORACLE 服務器同樣包含 PL/SQL 引擎 , 可以將游標變量在應用和服務器之間進行傳遞 .

.游標變量:

聲明游標實際上是創建一個指針 , 指針具有數據類型 REF X.REF 是 REFERENCE ,X 是表示類對象 . 因此 , 游標變量具有數據類型 REF CURSOR.

注 : 游標總是指向相同的查詢工作區 , 游標變量能夠指向不同的工作區 , 因此游標和游標變量不能互操作 .

1定義 REF CURSOR 類型 , 創建游標變量有兩個步驟:

1) 定義 REF CURSOR 類型

語法格式 :

TYPE ref_type_name

IS

REF CURSOR [RETURN return_type]

說明 :

ref_type_name 是游標變量中使用的類型 ;return_type 必須是一個記錄 (record) 或者數據庫表中的一行 .(rowtype)

下面定義 一個 REF CURSOR 類型游標

DELARE

TYPE xs_cur

IS

REF CURSOR RETURN xs%ROWTYPE;

注意 :

REF CURSOR類型既可以是強類型 , 也可以是弱類型 , 區別是強類型有返回類型 , 弱類型沒有. 如下所示

DECLARE

TYPE xs_cur IS REF CURSOR RETURN xs%ROWTYPE;-- 強類型

TYPE mycur IS REF CURSOR;-- 弱類型

2)聲明這種類型的游標變量 : 一旦定義了 REF CURSOR 類型就可以在 PL/SQL 塊或子程序中聲明這個游標變量. 如 :

DECARE

TYPE xs_cur REF CURSOR RETURN xs%ROWTYPE;

xscur xs_cur;

當然 , 在 RETURN 子句中也可以定義自定義的 RECORD 類型 , 如 :

DECLARE

TYPE kc_cj IS RECORD

(

kch number (4),

kcm number(10),

cj number(4,2)

);

TYPE kc_cjcur IS REF CURSOR RETURN kc_cj;

此外 , 也可以聲明游標變量作為函數和過程的參數 . 例如 :

DECLARE

TYPE xs_cur IS REF CURSOR RETURN xs%ROWTYPE;

PROCEDURE open_xs (xscur IN OUT xs_cur)IS

......................

3.控制游標變量

使用游標變量時 , 要遵循以下步驟 :OPEN-FETCH-CLOSE

OPEN 語句與多行查詢的游標變量相關聯 , 它執行查詢 , 標志結果集

語法格式 :

OPEN {cursor_variable|:host_cursor_variable }FOR

{

select_statement|dynamic_string[USING bind_argument[,......]]

}

如 :

IF NOT xscur%ISOPEN THEN

OPEN xscur FOR SELECT * FROM xs;

END IF ;

游標變量同樣可以使用游標屬性 :%FOUND,%ISOPEN,%ROWTYPE

在使用過程中 , 其他的 OPEN 語句可以為不同的查詢打開相同的游標變量 . 因此 , 在重新打開之前 , 不要關閉游標變量 . 可以打開游標 , 并作為參數傳遞給存儲過程 . 如 :

CREATE PACKAGE xs_data AS

...

TYPE xs_cur IS REF CURSOR RETURN xs%ROWTYPE;

RROCEDURE open_xs(xscur IN OUT xs_cur);

END xs_data;

CREATE PACKAGE BODY xs_data AS

...

PROCEDURE open_xs(xscur IN OUT xs_cur)

AS

BEGIN

OPEN xscur FOR SELECT * FROM xs;

END open_xs;

END xs_data;

當聲明一個游標變量作為打開游標變量子程序的參數時 , 必須定義 IN OUT 模式 . 也就是說 , 子程序可以將一個打開的游標變量傳遞給調用者 .

例子1:弱類型游標變量

declare
   type RefEmpCur  is ref cursor;  --聲明引用游標類型 游標返回的類型沒有限制
   EmpCur RefEmpCur;  --游標變量
   EmpRow emp%rowtype; --存儲游標查詢到得結果
   flag int:=0;
begin
   flag :=&flag;
   if flag=0 then
      open EmpCur  for select * from emp where sal>500 and sal<2000;
   elsif  flag=1 then
      open EmpCur for select * from  emp where sal>=2000;
   elsif  flag=2 then
      open EmpCur for select * from  dept;  --弱類型游標對目標表沒有限制,數據可以使來自任何表
   else
      open EmpCur for select * from emp;
   end if;
  /* for循環不能用于Ref游標,因為它是自動打開游標
   for EmpRow in EmpCur  loop
    DBMS_output.put_line('empno='||EmpRow.empno);
   end loop;
   */
   loop
      exit when EmpCur%notfound;  --如果沒有查詢到數據就退出
      fetch EmpCur into EmpRow;
      DBMS_output.put_line('empno='||EmpRow.empno);
   end loop;
   close EmpCur;
end;
/

例子2:強類型游標變量

declare
   type RefEmpCur  is ref cursor return emp%rowtype;  --游標僅能打開emp表的數據
   EmpCur RefEmpCur;  --游標變量
   EmpRow emp%rowtype; --存儲游標查詢到得結果
   flag int:=0;
begin
   flag :=&flag;
   if flag=0 then
      open EmpCur  for select * from emp where sal>500 and sal<2000;
   elsif  flag=1 then
      open EmpCur for select * from emp where sal>=2000;
   else
      open EmpCur for select * from emp;
   end if;

   loop
      exit when EmpCur%notfound;  --如果沒有查詢到數據就退出
      fetch EmpCur into EmpRow;
      DBMS_output.put_line('empno='||EmpRow.empno);
   end loop;
   close EmpCur;
end;
/

限制

1.不能在程序包中聲明游標變量

2.遠程子程序不能接受游標變量的值

3.不能使用比較操作符對游標變量進行相等或不相等測試

4.不能將空值賦予游標變量

5.表不能存儲游標變量的值

總結

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

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