在本章中,我們將討論和學習PL/SQL中的游標。 Oracle創(chuàng)建一個稱為上下文區(qū)域的內(nèi)存區(qū)域,用于處理SQL語句,它包含處理該語句所需的所有信息; 例如,處理的行數(shù)等。
游標是指向此上下文區(qū)域的指針。PL/SQL通過游標控制上下文區(qū)域,游標保存SQL語句返回的行(一個或多個)。 游標所在的行集稱為活動集。
可以命名一個游標,以便在程序中引用它來獲取和處理SQL語句返回的行,一次處理一個(行)。PL/SQL中有兩種類型的游標 -
當執(zhí)行SQL語句時,如果語句沒有顯式游標,則Oracle會自動創(chuàng)建隱式游標。程序員無法控制隱式游標及其信息。
每當發(fā)出DML語句(INSERT,UPDATE和DELETE)時,隱式游標與此語句相關聯(lián)。 對于INSERT操作,游標保存需要插入的數(shù)據(jù)。對于UPDATE和DELETE操作,游標標識將受到影響的行。
在PL/SQL中,可以將最近的隱式游標引用為SQL游標,它始終具有%FOUND,%ISOPEN,%NOTFOUND和%ROWCOUNT等屬性。 SQL游標具有額外的屬性%BULK_ROWCOUNT和%BULK_EXCEPTIONS,旨在與FORALL語句一起使用。下表提供了游標中最常用屬性的描述 -
編號 | 屬性 | 描述 |
---|---|---|
1 | %FOUND
|
如果INSERT ,UPDATE 或DELETE 語句影響一行或多行,或老兄SELECT INTO 語句返回一行或多行,則返回TRUE ,否則返回FALSE 。 |
2 | %NOTFOUND
|
與%FOUND 的邏輯相反。 如果INSERT,UPDATE或DELETE語句沒有影響任何行,或SELECT INTO語句未返回任何行,則返回TRUE。 否則返回FALSE。 |
3 | %ISOPEN
|
由于Oracle在執(zhí)行關聯(lián)的SQL語句后會自動關閉SQL游標,因此總是為隱式游標返回FALSE 。 |
4 | %ROWCOUNT
|
返回受INSERT ,UPDATE 或DELETE 語句,或者受SELECT INTO 語句影響的行數(shù)。 |
任何SQL游標屬性將被訪問為sql%attribute_name,如下例所示。
這里將使用在前幾章中創(chuàng)建和使用的CUSTOMERS表,表結構和數(shù)據(jù)參考: http://www.yiibai.com/plsql/plsql_variable_types.html
CREATE TABLE CUSTOMERS(
ID INT NOT NULL,
NAME VARCHAR (20) NOT NULL,
AGE INT NOT NULL,
ADDRESS CHAR (25),
SALARY DECIMAL (18, 2),
PRIMARY KEY (ID)
);
-- 插入數(shù)據(jù)
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 );
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (3, 'kaushik', 23, 'Kota', 2000.00 );
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 );
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 );
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (6, 'Komal', 22, 'MP', 4500.00 );
SQL
以下程序?qū)⒈碇忻總€客戶的工資增加500,并使用SQL%ROWCOUNT屬性來確定受影響的行數(shù) -
SET SERVEROUTPUT ON SIZE 99999;
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500;
IF sql%notfound THEN
dbms_output.put_line('沒有找到客戶信息~');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line('一共有:' || total_rows || ' 個客戶的工資被更新! ');
END IF;
END;
/
SQL
執(zhí)行上面示例代碼,得到以下結果 -
如果查詢了客戶表中的記錄,會發(fā)現(xiàn)工資已更新(增加了500) -
SQL> select id,name,salary from customers;
ID NAME SALARY
---------- -------------------- ----------
1 Ramesh 2500
2 Khilan 2000
3 kaushik 2500
4 Chaitali 7000
5 Hardik 9000
6 Komal 5000
SQL
顯式游標是用于獲得對上下文區(qū)域的更多控制的程序員定義的游標。應在PL/SQL塊的聲明部分中定義一個顯式游標。它是在一個返回多行的SELECT語句中創(chuàng)建的。
創(chuàng)建顯式游標的語法是 -
CURSOR cursor_name IS select_statement;
SQL
使用顯式游標包括以下步驟 -
聲明游標
聲明游標使用名稱和相關的SELECT語句來定義游標。 例如 -
CURSOR c_customers IS
SELECT id, name, address FROM customers;
SQL
打開游標
打開游標將為游標分配內(nèi)存,并使其準備好將SQL語句返回的行記錄數(shù)據(jù)提取到其中。例如,打開上面定義的游標,如下所示:
OPEN c_customers;
SQL
獲取游標獲取游標一次僅訪問一行。 例如,從上面打開的游標中獲取行,如下所示代碼:
FETCH c_customers INTO c_id, c_name, c_addr;
SQL
關閉游標
關閉游標意味著釋放分配的內(nèi)存。例如,關閉上面打開的游標,如下所示:
CLOSE c_customers;
SQL
以下是一個完整的例子來說明顯式游標的概念。
SET SERVEROUTPUT ON SIZE 99999;
DECLARE
c_id customers.id%type;
c_name customers.name%type;
c_addr customers.address%type;
CURSOR c_customers is
SELECT id, name, address FROM customers;
BEGIN
OPEN c_customers;
LOOP
FETCH c_customers into c_id, c_name, c_addr;
EXIT WHEN c_customers%notfound;
dbms_output.put_line(c_id || ' ' || c_name || ' ' || c_addr);
END LOOP;
CLOSE c_customers;
END;
/
SQL
執(zhí)行上面示例代碼,得到以下結果 -
更多建議: