Oracle數據庫數據編程SQL<3.3 PL/SQL 游標>

?游標(Cursor)是Oracle數據庫中用于處理查詢結果集的重要機制,它允許開發者逐行處理SQL語句返回的數據。

目錄

一、游標基本概念

1. 游標定義

2. 游標分類?

二、靜態游標

(一)顯式游標

【一】不帶參數,普通的顯示游標

1. 顯式游標使用步驟

2. 語法

3. 顯式游標的四個屬性

4. 注意事項

5.?%notfound 和普通循環一起用

6.?%found 和while循環一起用

7.?基本示例

【二】帶參數的顯示游標

1. 語法結構

2. 示例代碼

3. 練習

(二)隱式游標

1.隱式游標的四個屬性

2. 示例代碼

二、動態游標

【動態游標注意事項】

【強類型游標和弱類型游標區別】

【動態游標類型定義】

(一)強類型游標

(二)弱類型游標(SYS_REFCURSOR)

(三)動態游標

三、游標變量與批量處理

1. 游標變量

2. 批量提取(BULK COLLECT)

3. 批量處理與FORALL

四、游標最佳實踐

五、高級游標技術

1. 可更新游標?

2. 游標子查詢

3. 游標表達式(12c+)


一、游標基本概念

1. 游標定義

游標是一個指向上下文區域的指針,用于處理SQL語句的執行結果。它提供了以下能力:

  • 逐行訪問結果集

  • 跟蹤當前處理的行

  • 對結果集進行修改或刪除操作

2. 游標分類?

游標類型描述生命周期控制方式
靜態隱式游標Oracle自動為每條SQL語句創建?? ?單條SQL執行期間Oracle自動管理
顯式游標開發者顯式定義從OPEN到CLOSE開發者手動控制
動態REF游標動態游標,運行時確定靈活控制開發者控制

二、靜態游標

(一)顯式游標

顯示的游標:在declare的部分用is顯示了的游標

【一】不帶參數,普通的顯示游標

1. 顯式游標使用步驟

(1)聲明游標:定義游標及其關聯的SELECT語句

(2)打開游標:執行查詢,填充結果集

(3)提取數據:從結果集中獲取行數據

(4)關閉游標:釋放資源

2. 語法
-- 1. 聲明游標
CURSOR cursor_name [(parameters)][RETURN return_type]IS select_statement;-- 2. 打開游標
OPEN cursor_name [(parameters)];-- 3. 提取數據
FETCH cursor_name INTO variable_list;-- 4. 關閉游標
CLOSE cursor_name;-- 5. 舉例
declare
cursor cur_name is select語句;---聲明一個顯示游標
begin open cur_name;--打開游標fetch cur_name into 變量;--賦值變量,提取記錄dbms_output.put_line()---打印close cur_name;--關閉游標
end;
/
3. 顯式游標的四個屬性
屬性返回值描述說明

cursor_name%FOUND

布爾值

如果最近一次

FETCH返回行則為TRUE

游標的指針是否有值(有)對

(沒有)?錯

cursor_name%NOTFOUND

布爾值

如果最近一次

FETCH未返回行則為TRUE

游標的指針是否沒值(有值)錯,

(沒值)對,理論上可以返回空

在open之后fetch之前可以返回空

cursor_name%ROWCOUNT

數值

到目前為止已提取的行數

游標的指針已經指了幾行,返回數值,

但是要賦給變量才能顯示

返回最近一次從游標讀取的數據

cursor_name%ISOPEN

布爾值

如果游標已打開則為TRUE

判斷是否打開游標(打開)對

(沒有)錯

4. 注意事項

首先聲明一個游標,使用之前先打開游標,提取記錄只能一行,可以多列

使用完游標要關閉游標,可以通過open打開游標繼續使用

5.?%notfound 和普通循環一起用
 open→loop fetch→exit when %notfound→打印→end loop→close【舉例1】declarecursor cur_a is select * from emp;---聲明一個顯示游標v_emp emp%rowtype;---聲明變量v1    varchar2(20);---聲明變量
beginopen cur_a;--打開游標loop/*普通循環*/                                 fetch cur_a  into v_emp;/*賦值變量,抓取記錄*/            exit when cur_a%notfound;/*和普通循環一起用*/                    dbms_output.put_line(v_emp.ename);                              end loop;/*結束循環*/                                                close cur_a;/*關閉游標*/                      end;
/-- LOOP循環語法 
declare 部分;
beginloop 要執行的語句;exit when 退出的條件;end loop;
end;
注意事項:進入循環不需要條件
6.?%found 和while循環一起用
open→fetch→while %found loop→打印→fetch→end loop→close【舉例】
declarecursor cur_a is select * from emp;v_emp emp%rowtype;
beginopen cur_a;fetch cur_a into v_emp;while cur_a%found loopdbms_output.put_line(v_emp.ename);fetch cur_a into v_emp;end loop;close cur_a;
end;
7.?基本示例
DECLARE-- 1. 聲明游標CURSOR emp_cursor ISSELECT employee_id, last_name, salaryFROM employeesWHERE department_id = 10;v_emp_id employees.employee_id%TYPE;v_name employees.last_name%TYPE;v_sal employees.salary%TYPE;
BEGIN-- 2. 打開游標OPEN emp_cursor;-- 3. 提取數據LOOPFETCH emp_cursor INTO v_emp_id, v_name, v_sal;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp_id || ': ' || v_name || ', ' || v_sal);END LOOP;-- 4. 關閉游標CLOSE emp_cursor;
END;
/1、輸出emp表工資前十名的員工姓名和薪資
declarecursor cur_1 isselect ename, salfrom (select ename, sal from emp order by sal desc)where rownum <= 10;v_n emp.ename%type;v_s emp.sal%type;
beginopen cur_1;loopfetch cur_1 into v_n, v_s;exit when cur_1%notfound;dbms_output.put_line('姓名:' || v_n || '薪資:' || v_s);end loop;close cur_1;
end;
/
-------------------
declarecursor cur_1 isselect ename, salfrom (select ename, sal from emp order by sal desc)where rownum <= 10;v_n emp.ename%type;v_s emp.sal%type;
beginopen cur_1;fetch cur_1 into v_n, v_s;while cur_1%found loopdbms_output.put_line('姓名:' || v_n || '薪資:' || v_s);fetch cur_1 into v_n, v_s;end loop;close cur_1;
end;
/

【二】帶參數的顯示游標

游標可以接受參數,使查詢更加靈活:

1. 語法結構
CURSOR cursor_name (parameter1 datatype, parameter2 datatype, ...)IS select_statement;declarecursor cur_name(變量 類型) is select語句;---聲明一個顯示游標
begin open cur_name(變量);--打開游標fetch cur_name into 變量;--賦值變量,提取記錄close cur_name;--關閉游標
end;
2. 示例代碼
DECLARE-- 帶參數的游標CURSOR emp_cursor (p_dept_id NUMBER, p_min_sal NUMBER) ISSELECT employee_id, last_name, salaryFROM employeesWHERE department_id = p_dept_idAND salary >= p_min_sal;-- 記錄類型變量v_emp_record emp_cursor%ROWTYPE;
BEGIN-- 打開游標并傳入參數OPEN emp_cursor(10, 5000);LOOPFETCH emp_cursor INTO v_emp_record;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ': ' || v_emp_record.last_name || ', ' || v_emp_record.salary);END LOOP;CLOSE emp_cursor;
END;
/declarecursor cur_1(v1 number) is select sal from emp where empno = v1; --聲明一個帶參數的顯示游標v_s emp.sal%type; --負責接收的變量
beginopen cur_1(&a); ---(7788)即為(v1 number)fetch cur_1 into v_s;dbms_output.put_line(v_s);close cur_1;
end;
3. 練習
【1】輸出工作是MANAGER的姓名、工資、;工作是SALESMAN的姓名、傭金;
工作是CLERK的姓名、入職日期。
declarecursor cur_2(v1 varchar2) isselect * from emp where job = v1;v_emp emp%rowtype;
beginopen cur_2('MANAGER');---loopfetch cur_2into v_emp;exit when cur_2%notfound;dbms_output.put_line(v_emp.ename ||' '|| v_emp.sal);end loop;close cur_2;open cur_2('SALESMAN');loopfetch cur_2into v_emp;exit when cur_2%notfound;dbms_output.put_line(v_emp.ename ||' '|| v_emp.comm);end loop;close cur_2;open cur_2('CLERK');loopfetch cur_2into v_emp;exit when cur_2%notfound;dbms_output.put_line(v_emp.ename ||' '|| to_char(v_emp.hiredate,'yyyy-mm-dd'));end loop;close cur_2;
end;
/【2】輸出工作是MANAGER的姓名、工作、;工作是SALESMAN的姓名、傭金;
工作是CLERK的姓名、入職日期。
declarecursor cur_xx(v_1 emp.job%type) isselect * from emp where job = v_1;v_emp emp%rowtype;
beginopen cur_xx('MANAGER');loopfetch cur_xxinto v_emp;exit when cur_xx%notfound;dbms_output.put_line('員工姓名:'||v_emp.ename ||'    '||'職位:'|| v_emp.job);end loop;close cur_xx;open cur_xx('SALESMAN');loopfetch cur_xxinto v_emp;exit when cur_xx%notfound;dbms_output.put_line('員工姓名:'||v_emp.ename ||'    '||'工資:'|| v_emp.sal);end loop;close cur_xx;open cur_xx('CLERK');loopfetch cur_xxinto v_emp;exit when cur_xx%notfound;dbms_output.put_line('員工姓名:'||v_emp.ename ||'    '||'入職日期:'||v_emp.hiredate);end loop;close cur_xx;
end;
/-----------------------------------------------------------------------------------------
輸出名字中包含%的人
select * from emp where ename like '%'||v1||'%' or ename like'%'||v_2||'%'【3】打印名字中包含A的人數,包含E的平均工資,包含o的總工資
declarecursor cur_3(v1 varchar2) is---先讓cur_3有了selecteselect count(sal), avg(sal), sum(sal)from empwhere ename like '%' || v1 || '%';----注意學習這種方法--聲明一個帶參數的顯示游標cur_3v_2 number;v_3 number;v_4 number;
----------------添加負責接收的變量
beginopen cur_3('A');loopfetch cur_3---又從cur_3里提取值賦值給變量v_2,v_3,v_4into v_2, v_3, v_4;exit when cur_3%notfound;dbms_output.put_line(v_2);end loop;close cur_3;---------------open cur_3('E');loopfetch cur_3into v_2, v_3, v_4;exit when cur_3%notfound;dbms_output.put_line(v_3);end loop;close cur_3;----------------open cur_3('O');loopfetch cur_3into v_2, v_3, v_4;exit when cur_3%notfound;dbms_output.put_line(v_4);end loop;close cur_3;----------------
end;

(二)隱式游標

主要應用于增加刪除更新數據,Oracle為每條DML語句自動創建隱式游標,當執行SQL語句的時候,這個游標是處理該語句的工作區域。在使用的時候要使用隱式游標的默認名稱SQL。?

1.隱式游標的四個屬性

屬性返回描述說明
cursor_name%FOUND布爾值如果DML操作影響至少一行返回TRUE

游標的游標中是否有值,返回最近一次的結果,成功(對)否則(錯)

cursor_name%NOTFOUND布爾值如果DML操作未影響任何行返回TRUE

游標的游標中是否有值,返回最近一次的結果,成功(錯)

cursor_name%ROWCOUNT數值返回DML操作影響的行數

返回最近一次從游標中讀取到的記錄--數值類型

cursor_name%ISOPEN布爾值對隱式游標總是返回FALSE

判斷是否打開游標。永遠返回錯

?補充:閃回不僅可以閃回刪除前的數據,也可以返回之前某一時間點的數據

2. 示例代碼

BEGIN-- 更新操作UPDATE employees SET salary = salary * 1.1 WHERE department_id = 10; -- 檢查隱式游標屬性IF SQL%FOUND THENDBMS_OUTPUT.PUT_LINE('更新了 ' || SQL%ROWCOUNT || ' 條記錄');END IF;-- 刪除操作DELETE FROM temp_employees WHERE employee_id = 9999;IF SQL%NOTFOUND THENDBMS_OUTPUT.PUT_LINE('未刪除任何記錄');END IF;
END;
----------------------------------------------------------------
----------------------------------------------------------------
/
begindelete from emp001 where deptno=10;--3--dbms_output.put_line('刪除了'||sql%rowcount||'行');delete from emp001 where deptno=20;--5if sql%found thendbms_output.put_line('刪除了'||sql%rowcount||'行') ;end if;end;
/
----------------------------------------------------------------
begin--dbms_output.put_line('刪除了'||sql%rowcount||'行');delete from emp001 where deptno in (10,20);--5if sql%found thendbms_output.put_line('刪除了'||sql%rowcount||'行') ;end if;
end;
/
----------------------------------------------------------------
----------------------------------------------------------------
declare
v_name csm_product.product_name%type;
begininsert into test_t values(1);if sql%found thendbms_output.put_line('收到影響的行數為:'||sql%rowcount);end if;rollback;
end;
----------------------------------------------------------------
----------------------------------------------------------------
declare
cursor v_cur is select * from test_t
beginif v_cur%isopen thendbms_output.put_line('游標已經打開');elsedbms_output.put_line('游標未打開');end if;open v_cur;if v_cur%isopen thendbms_output.put_line('游標已經打開');end if;close v_cur;insert into test_t valuse(1);if sql%found thendbms_output.put_line('執行成功,影響的行數:'||sql%rowcount)elsif sql%notfound thendbms_output.put_line('執行失敗');end if;rollback;
end;

二、動態游標

【動態游標注意事項】

1、使用動態游標必須聲明游標類型

2、只要列的格式相同,可以同時打開多表

【強類型游標和弱類型游標區別】

1、強類型游標有return,open時查詢得到的結果要和return后的表的數據類型、結構、順序一致。

2、沒有return,open時查詢的結果比較自由,fetch的時候into給的變量要和SQL查詢的類型結構數量一致。

【動態游標類型定義】

TYPE cursor_type IS REF CURSOR [RETURN return_type];

(一)強類型游標

DECLARETYPE emp_cursor_type IS REF CURSOR RETURN employees%ROWTYPE;emp_cursor emp_cursor_type;v_emp employees%ROWTYPE;
BEGINOPEN emp_cursor FOR SELECT * FROM employees WHERE department_id = 20;LOOPFETCH emp_cursor INTO v_emp;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp.employee_id || ': ' || v_emp.last_name);END LOOP;CLOSE emp_cursor;
END;
/declaretype cur_name_ref is ref cursor return emp%rowtype; --emp可以自定義,只是聲明了一個類型cur_1 cur_name_ref;v_emp    emp%rowtype;
begin
--------------------------------------------------------------------open cur_1 for select * from emp;-------------同時打開多表---------fetch cur_1into v_emp;dbms_output.put_line(v_emp.deptno || v.emp.ename || v_emp.job);close cur_1;
--------------------------------------------------------------------open cur_1 for select * from emp001;---------同時打開多表----------fetch cur_1into v_emp;dbms_output.put_line(v_emp.deptno || v.emp.ename || v_emp.job);close cur_1;
end;

(二)弱類型游標(SYS_REFCURSOR)

DECLAREemp_cursor SYS_REFCURSOR;v_emp_id employees.employee_id%TYPE;v_emp_name employees.last_name%TYPE;
BEGIN-- 打開第一個查詢OPEN emp_cursor FOR SELECT employee_id, last_name FROM employees WHERE department_id = 10;DBMS_OUTPUT.PUT_LINE('部門10員工:');LOOPFETCH emp_cursor INTO v_emp_id, v_emp_name;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp_id || ': ' || v_emp_name);END LOOP;CLOSE emp_cursor;-- 重用游標執行不同查詢OPEN emp_cursor FOR SELECT department_id, department_name FROM departments;DBMS_OUTPUT.PUT_LINE('所有部門:');LOOPFETCH emp_cursor INTO v_emp_id, v_emp_name;  -- 重用變量EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp_id || ': ' || v_emp_name);END LOOP;CLOSE emp_cursor;
END;
/declaretype cur_name_ref is ref cursor;---沒有return,和強類型的區別就在于此cur_name cur_name_ref;v_emp    emp%rowtype;
beginopen cur_name for select * from emp;-------------同時打開多表---------------fetch cur_nameinto v_emp;dbms_output.put_line(v_emp.deptno || v.emp.ename || v_emp.job);close cur_1;---注意游標開一次,關一次,不然一直開著耗內存。open cur_name for select * from emp001;--------同時打開多表---------------fetch cur_nameinto v_emp;dbms_output.put_line(v_emp.deptno || v.emp.ename || v_emp.job);close cur_1;
end;【練習題】
1、輸出工作是MANAGER的姓名、工資;工作是SALESMAN的姓名、傭金;
工作是CLERK的姓名、入職日期。
declaretype  cur_1_ref is ref cursor; ---沒有returncur_1 cur_1_ref;v1    varchar2(20);v2    number;v3    date;
beginopen cur_1 forselect ename, sal from emp where job = 'MANAGER';loopfetch cur_1into v1, v2;exit when cur_1%notfound;dbms_output.put_line(v1 || v2);end loop;open cur_1 forselect ename, sal from emp where job = 'SALESMAN';loopfetch cur_1into v1, v2;exit when cur_1%notfound;dbms_output.put_line(v1 || v2);end loop;open cur_1 forselect ename, hiredate from emp where job = 'CLERK';loopfetch cur_1into v1, v3;exit when cur_1%notfound;dbms_output.put_line(v1 || v3);end loop;
end;
/--用弱類型游標,打印emp名字中包含A的人數,dept部門編號的平均數
--salgrade 第三等級的hisal
declaretype cur_name_ref is ref cursor;cur_gam cur_name_ref;v_1     number;
beginopen cur_gam forselect count(ename) from emp where ename like '%A%';----單列單行不用循環fetch cur_gaminto v_1;dbms_output.put_line('名字包含A的人數:' || v_1);close cur_gam;open cur_gam forselect avg(deptno) from dept;----單列單行不用循環fetch cur_gaminto v_1;dbms_output.put_line('部門編號的平均數:' || v_1);close cur_gam;open cur_gam forselect hisal from salgrade where grade = 3;----單列單行不用循環fetch cur_gaminto v_1;dbms_output.put_line('第三等級的hisal:' || v_1);close cur_gam;
end;
--------如果多行多列,加入循環的寫法
declaretype cur_name_ref is ref cursor;cur_gam cur_name_ref;v_1 number;
beginopen cur_gam forselect count(ename) from emp where ename like '%A%';loopfetch cur_gaminto v_1;exit when cur_gam%notfound;dbms_output.put_line('名字包含A的人數:'||v_1);end loop;close cur_gam;
-----------------------open cur_gam forselect avg(deptno) from dept;loopfetch cur_gaminto v_1;exit when cur_gam%notfound;dbms_output.put_line('部門編號的平均數:'||v_1);end loop;close cur_gam;
-----------------------------open cur_gam forselect hisal from salgrade where grade=3;loopfetch cur_gaminto v_1;exit when cur_gam%notfound;dbms_output.put_line('第三等級的hisal:'||v_1);end loop;close cur_gam;
end;

(三)動態游標

【語法】
declarecur_name sys_refcursor;v1       number;v2       varchar2(20);
beginopen cur_name forselect empno, ename from emp where empno = 7788;fetch cur_nameinto v1, v2;dbms_output.put_line(v1 || v2);close cur_name;
--------------open cur_name forselect empno, ename from emp where deptno = 20;fetch cur_nameinto v1, v2;dbms_output.put_line(v1 || v2);close cur_name;
end;【練習題】
1、打印10部門的人員姓名和部門地址,打印20部門的工資和工資等級
declarecur_1 sys_refcursor;ve       varchar2(20);vc       varchar2(20);vs       number;vg       number;
beginopen cur_1 forselect e.ename,d.loc from emp e,dept d where e.deptno=d.deptno and d.deptno=10;loopfetch cur_1into ve, vc;exit when cur_1%notfound;dbms_output.put_line(ve ||'  '|| vc);end loop;open cur_1 forselect e.sal, s.grade from emp e,salgrade s where e.sal between s.losal and s.hisal and e.deptno=20;loopfetch cur_1into vs, vg;exit when cur_1%notfound;dbms_output.put_line(vs ||' '|| vg);end loop;close cur_1;
end;
/2、用動態游標里面的動態游標,打印emp名字中包含A的人數,dept部門編號的平均數,salgrade 第三等級的hisal
declarecur_2 sys_refcursor;v1    number;
beginopen cur_2 forselect count(ename) from emp where ename like '%A%';fetch cur_2into v1;dbms_output.put_line('名字包含A的人數:' || v1);close cur_2;
----------------------open cur_2 forselect avg(deptno) from dept;fetch cur_2into v1;dbms_output.put_line('部門編號的平均數:' || v1);close cur_2;
-----------------------open cur_2 forselect hisal from salgrade where grade = 3;fetch cur_2into v1;dbms_output.put_line('第三等級的hisal:' || v1);close cur_2;
end;
/

三、游標變量與批量處理

1. 游標變量

DECLARETYPE emp_cursor_type IS REF CURSOR;emp_cursor emp_cursor_type;PROCEDURE process_employees (p_cursor IN emp_cursor_type) ISv_emp employees%ROWTYPE;BEGINLOOPFETCH p_cursor INTO v_emp;EXIT WHEN p_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_emp.employee_id || ': ' || v_emp.last_name);END LOOP;END;
BEGINOPEN emp_cursor FOR SELECT * FROM employees WHERE department_id = 10;process_employees(emp_cursor);CLOSE emp_cursor;
END;
/

2. 批量提取(BULK COLLECT)

DECLARECURSOR emp_cursor ISSELECT employee_id, last_name, salaryFROM employeesWHERE department_id = 10;-- 定義集合類型TYPE emp_id_array IS TABLE OF employees.employee_id%TYPE;TYPE name_array IS TABLE OF employees.last_name%TYPE;TYPE sal_array IS TABLE OF employees.salary%TYPE;v_ids emp_id_array;v_names name_array;v_sals sal_array;
BEGINOPEN emp_cursor;-- 批量提取數據FETCH emp_cursor BULK COLLECT INTO v_ids, v_names, v_sals;CLOSE emp_cursor;-- 處理批量數據FOR i IN 1..v_ids.COUNT LOOPDBMS_OUTPUT.PUT_LINE(v_ids(i) || ': ' || v_names(i) || ', ' || v_sals(i));END LOOP;
END;
/

3. 批量處理與FORALL

DECLARETYPE id_array IS TABLE OF employees.employee_id%TYPE;TYPE sal_array IS TABLE OF employees.salary%TYPE;v_ids id_array := id_array(101, 102, 103, 104, 105);v_new_sals sal_array;
BEGIN-- 批量查詢SELECT salary BULK COLLECT INTO v_new_salsFROM employeesWHERE employee_id IN (SELECT COLUMN_VALUE FROM TABLE(v_ids));-- 批量更新FORALL i IN 1..v_ids.COUNTUPDATE employeesSET salary = v_new_sals(i) * 1.1WHERE employee_id = v_ids(i);COMMIT;DBMS_OUTPUT.PUT_LINE('成功更新 ' || SQL%ROWCOUNT || ' 條記錄');
END;
/

四、游標最佳實踐

1.??及時關閉游標:避免資源泄漏

BEGINOPEN emp_cursor;-- 處理數據
EXCEPTIONWHEN OTHERS THENIF emp_cursor%ISOPEN THENCLOSE emp_cursor;END IF;RAISE;
END;

2. 使用游標FOR循環:簡化代碼,自動處理打開/關閉

3. 批量操作:對大結果集使用BULK COLLECT和FORALL

4. 參數化游標:提高代碼重用性

5. 限制返回行數:避免內存問題

FETCH emp_cursor BULK COLLECT INTO v_emps LIMIT 1000;

6. 使用合適的作用域:在包中定義常用游標

7. 性能監控:檢查游標SQL的執行計劃

五、高級游標技術

1. 可更新游標?

DECLARECURSOR emp_cursor ISSELECT employee_id, last_name, salaryFROM employeesWHERE department_id = 10FOR UPDATE OF salary NOWAIT;v_raise_percent NUMBER := 0.1;
BEGINFOR emp_rec IN emp_cursor LOOPUPDATE employeesSET salary = salary * (1 + v_raise_percent)WHERE CURRENT OF emp_cursor;END LOOP;COMMIT;
END;
/

2. 游標子查詢

DECLARECURSOR dept_cursor ISSELECT d.department_id, d.department_name,CURSOR(SELECT employee_id, last_nameFROM employeesWHERE department_id = d.department_id) AS emp_cursorFROM departments dWHERE d.location_id = 1700;v_emp_cursor SYS_REFCURSOR;v_emp_id employees.employee_id%TYPE;v_emp_name employees.last_name%TYPE;
BEGINFOR dept_rec IN dept_cursor LOOPDBMS_OUTPUT.PUT_LINE('部門: ' || dept_rec.department_name);v_emp_cursor := dept_rec.emp_cursor;LOOPFETCH v_emp_cursor INTO v_emp_id, v_emp_name;EXIT WHEN v_emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE('  ' || v_emp_id || ': ' || v_emp_name);END LOOP;CLOSE v_emp_cursor;END LOOP;
END;
/

3. 游標表達式(12c+)

DECLARECURSOR dept_cursor ISSELECT d.department_id, d.department_name,CURSOR(SELECT e.employee_id, e.last_nameFROM employees eWHERE e.department_id = d.department_id) AS emp_curFROM departments d;
BEGINFOR dept_rec IN dept_cursor LOOPDBMS_OUTPUT.PUT_LINE('部門: ' || dept_rec.department_name);FOR emp_rec IN dept_rec.emp_cur LOOPDBMS_OUTPUT.PUT_LINE('  員工: ' || emp_rec.last_name);END LOOP;END LOOP;
END;
/

游標是Oracle PL/SQL中處理結果集的核心機制,掌握各種游標技術可以顯著提高數據庫應用程序的效率和靈活性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/74139.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/74139.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/74139.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

逗萬DareWorks|創意重構書寫美學,引領新潮無界的文創革命

當傳統文具陷入同質化泥潭時&#xff0c;逗萬DareWorks品牌猶如一顆璀璨的明星&#xff0c;以其獨特的創意理念和卓越的產品品質&#xff0c;迅速贏得了廣大消費者的青睞。 逗萬DareWorks隸屬于東莞司貿文教贈品有限公司&#xff0c;后者深耕制筆行業45年&#xff0c;占地4.6萬…

寫Prompt的技巧和基本原則

一.基本原則 1.一定要描述清晰你需要大模型做的事情&#xff0c;不要模棱兩可 2.告訴大模型需要它做什么&#xff0c;不需要做什么 改寫前: 請幫我推薦一些電影 改寫后: 請幫我推薦2025年新出的10部評分比較高的喜劇電影&#xff0c;不要問我個人喜好等其他問題&#xff…

【React】基于 React+Tailwind 的 EmojiPicker 選擇器組件

1.背景 React 寫一個 EmojiPicker 組件&#xff0c;基于 emoji-mart 組件二次封裝。支持添加自定義背景 、Emoji 圖標選擇&#xff01;并在頁面上展示&#xff01; 2.技術棧 emoji-mart/data 、emoji-mart : emoji 圖標庫、元數據 tailwindcss: 原子化 CSS 樣式庫 antd : 組…

Qt中繪制不規則控件

在Qt中繪制不規則控件可通過設置遮罩&#xff08;Mask&#xff09;實現。以下是詳細步驟: ?繼承目標控件?&#xff1a;如QPushButton或QWidget。?重寫resizeEvent?&#xff1a;當控件大小變化時&#xff0c;更新遮罩形狀。?創建遮罩區域?&#xff1a;使用QRegion或QPain…

Parallel_Scheduling_of_DAGs_under_Memory_Constraints論文閱讀

內存約束下的 DAG 并行調度 點擊閱讀原文語雀鏈接更清晰 摘要 科學工作流通常被建模為任務的有向無環圖&#xff08;DAG&#xff09;&#xff0c;這些任務代表計算模塊及其依賴關系&#xff0c;依賴關系表現為任務生成的數據被其他任務使用。這種形式化方法允許使用運行時系統&…

探索MVC、MVP、MVVM和DDD架構在不同編程語言中的實現差異

MVC與MVP/MVVM/DDD架構對比&#xff0c;不同語言實現 MVC 分層架構設計概述 模型-視圖-控制器&#xff08;Model-View-Controller&#xff0c;簡稱 MVC&#xff09;是一種經典軟件架構設計&#xff0c;通過分層解耦&#xff0c;使得系統結構清晰和易于維護&#xff0c;具有良…

一文讀懂 UML:基礎概念與體系框架

UML 圖是一種標準化的建模語言&#xff0c;在軟件開發和系統設計等領域有著廣泛的應用。以下是對 UML 圖各類圖的詳細介紹&#xff1a; 1.用例圖 定義&#xff1a;用例圖是從用戶角度描述系統功能的模型圖&#xff0c;展現了系統的參與者與用例之間的關系。作用&#xff1a;幫…

Spring 及 Spring Boot 條件化注解(15個)完整列表及示例

Spring 及 Spring Boot 條件化注解完整列表及示例 1. 所有條件化注解列表 Spring 和 Spring Boot 提供了以下條件化注解&#xff08;共 15 個&#xff09;&#xff0c;用于在配置類或方法上實現條件化注冊 Bean 或配置&#xff1a; 注解名稱作用來源框架Conditional自定義條件…

【Kafka】深入探討 Kafka 如何保證一致性

文章目錄 Kafka 基本概念回顧?副本角色? 數據寫入一致性?同步副本&#xff08;ISR&#xff09;集合?數據讀取一致性?故障處理與一致性恢復?總結? 在分布式系統領域&#xff0c;數據一致性是至關重要的一環。作為一款高性能的分布式消息隊列系統&#xff0c;Kafka 在設計…

從入門到精通:SQL注入防御與攻防實戰——紅隊如何突破,藍隊如何應對!

引言&#xff1a;為什么SQL注入攻擊依然如此強大&#xff1f; SQL注入&#xff08;SQL Injection&#xff09;是最古老且最常見的Web應用漏洞之一。盡管很多公司和組織都已經采取了WAF、防火墻、數據庫隔離等防護措施&#xff0c;但SQL注入依然在許多情況下能夠突破防線&#…

【算法day27】有效的數獨——請你判斷一個 9 x 9 的數獨是否有效。只需要 根據以下規則 ,驗證已經填入的數字是否有效即可。

36. 有效的數獨 請你判斷一個 9 x 9 的數獨是否有效。只需要 根據以下規則 &#xff0c;驗證已經填入的數字是否有效即可。 數字 1-9 在每一行只能出現一次。 數字 1-9 在每一列只能出現一次。 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。&#xff08;請參考示例…

leetcode 2360. 圖中的最長環 困難

給你一個 n 個節點的 有向圖 &#xff0c;節點編號為 0 到 n - 1 &#xff0c;其中每個節點 至多 有一條出邊。 圖用一個大小為 n 下標從 0 開始的數組 edges 表示&#xff0c;節點 i 到節點 edges[i] 之間有一條有向邊。如果節點 i 沒有出邊&#xff0c;那么 edges[i] -1 。…

PySpur: AI 智能體可視化開發平臺

GitHub&#xff1a;https://github.com/PySpur-Dev/pyspur 更多AI開源軟件&#xff1a;發現分享好用的AI工具、AI開源軟件、AI模型、AI變現 - 小眾AI PySpur是一個開源的輕量級可視化AI智能體工作流構建器&#xff0c;旨在簡化AI系統的開發流程。通過拖拽式界面&#xff0c;用戶…

vcpkg安裝及使用教程,以安裝matio庫解析mat文件為例

vcpkg安裝及使用教程,以安裝matio庫解析mat文件為例 1. vcpkg安裝2 安裝matio三方庫3 將三方庫集成到VS中3.1 全局集成3.2 集成到特定工程4 結語Vcpkg 是微軟開發的一款開源的 C/C++ 包管理工具,旨在簡化 C/C++ 項目依賴庫的安裝和管理。它支持跨平臺(Windows、Linux、macO…

LLM架構解析:NLP基礎(第一部分)—— 模型、核心技術與發展歷程全解析

本專欄深入探究從循環神經網絡&#xff08;RNN&#xff09;到Transformer等自然語言處理&#xff08;NLP&#xff09;模型的架構&#xff0c;以及基于這些模型構建的應用程序。 本系列文章內容&#xff1a; NLP自然語言處理基礎&#xff08;本文&#xff09;詞嵌入&#xff0…

【Rtklib入門指南】2. 使用RTKLIB GUI進行觀測數據分析

數據準備 下載2025年1月1日的香港CORS站數據和觀測星歷&#xff0c;詳情參照如下博客&#xff1a; 使用GAMP_GOOD進行hk數據下載教程-CSDN博客 分析工具 RTKLIB 2.4.3 demo5&#xff08;也可以選用RTKLIB2.4.2&#xff0c;但不建議使用RTKLIB2.4.3&#xff09; 分析流程 …

suse15 sp1使用華為云軟件源yum源zypper源

登錄suse15終端&#xff0c; cd /etc/zypp/repos.d/進入目錄后執行以下命令&#xff1a; zypper ar -fcg https://mirrors.huaweicloud.com/opensuse/distribution/leap/15.1/repo/oss HuaWeiCloud:15.1:OSS zypper ar -fcg https://mirrors.huaweicloud.com/opensuse/distribu…

首屏加載時間優化解決

&#x1f916; 作者簡介&#xff1a;水煮白菜王&#xff08;juejin/csdn同名&#xff09; &#xff0c;一位前端勸退師 &#x1f47b; &#x1f440; 文章專欄&#xff1a; 高德AMap專欄 &#xff0c;記錄一下平時學習在博客寫作中記錄&#xff0c;總結出的一些開發技巧?。 感…

Sentinel[超詳細講解]-1

定義一系列 規則 &#x1f47a;&#xff0c;對資源進行 保護 &#x1f47a;&#xff0c; 如果違反的了規則&#xff0c;則拋出異常&#xff0c;看是否有fallback兜底處理&#xff0c;如果沒有則直接返回異常信息&#x1f60e; 1. 快速入門 1.1 引入 Sentinel 依賴 <depend…

02-Docker 使用

docker:快速構建、運行、管理應用的工具,可以幫助我們下載應用鏡像,創建并運行鏡像的容器,從而快速部署應用 1、部署mysql 先停掉虛擬機中的MySQL,確保你的虛擬機已經安裝Docker,且網絡開通的情況下,執行下面命令即可安裝MySQL(注意:若服務器上已經有mysql 占用了330…