目标
游标
•示例:显示当用户没有创建一个显示游标以获得多行结果时发生的情况。
DECLARE
v_title books.title%TYPE;
v_retail books.retail%TYPE;
BEGIN
SELECT title,retail
INTO v_title,v_retail
FROM books NATURAL JOIN orderitems
WHERE order#=1012;
DBMS_OUTPUT.PUT_LINE('Books title: '||v_title||' Retail price: '||v_retail);
END;
声明显示游标
CURSOR cursor_name IS
selectquery;
•前面示例中,需要一个显示游标来检索订单1012中的图书的书名和零售价。
DECLARE
CURSOR books_cursor IS
SELECT title,retail
FROM books NATURAL JOIN orderitems
WHERE order#=1012;
打开显示游标
OPEN cursor_name;
示例:
OPEN books_cursor;
打开游标之后,可以将游标中包含的数据赋给变量以进行处理
关闭显示游标
CLOSE cursor_name
CLOSE books_cursor;
从显示游标中提取数据
FETCH cursor_name INTO variablename[,…variablename];
FETCH books_cursor INTO v_title,v_retail;
示例:显示游标的使用
DECLARE
v_title books.title%TYPE;
v_retail books.retail%TYPE;
CURSOR books_cursor IS
SELECT title,retail
FROM books NATURAL JOIN orderitems
WHERE order#=1012;
BEGIN
OPEN books_cursor;
FETCH books_cursor INTO v_title,v_retail;
DBMS_OUTPUT.PUT_LINE('Books title: '||v_title||' Retail price: '||v_retail);
CLOSE books_cursor;
END;
结果
结果中发现只有一行数据输出
独立执行这个PL/SQL块的SELECT语句,显示
游标属性 | 说明 |
%ROWCOUNT | 指出处理的行 |
%FOUND | 如果处理了一行或多行,这包含值TRUE——如果没有处理行,则为FALSE |
%NOTFOUND | 如果没有处理行,则包含值TRUE——如果处理了一行或多行,则为FALSE |
%ISOPEN | 如果在处理之后不关闭数据,这包含值TRUE——如果关闭游标,则为FALSE。在发生隐式游标时,由于它是自动关闭的,因此这个值在处理之后总是FALSE |
DECLARE
v_title books.title%TYPE;
v_retail books.retail%TYPE;
CURSOR books_cursor IS
SELECT title,retail
FROM books NATURAL JOIN orderitems
WHERE order#=1012;
BEGIN
OPEN books_cursor;
LOOP
FETCH books_cursor INTO v_title,v_retail;
EXIT WHEN books_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Books title: '||v_title||' Retail price: '||v_retail);
END LOOP;
CLOSE books_cursor;
END;
游标FOR循环
FOR record_name IN cursor_name LOOP
statements;
[statement;…]
END LOOP;
说明:不是检索游标中的行并向变量赋值,而是 将行的内容赋给一个记录 。“记录”是一种复合数据类型 , 可以使其结构与检索的行的结构相同 。要想指定记录的结构与检索的行的结构相同,可以在定义记录时使用 %ROWTYPE 属性。与 %TYPE 属性相似, %TYPE 用来定义基于一个单独列的变量,而 %ROWTYPE 属性定义了基于数据库表中包含的所有列的记录。
示例:包含游标FOR循环的PL/SQL块
DECLARE
CURSOR books_cursor IS
SELECT title,retail
FROM books NATURAL JOIN orderitems
WHERE order#=1012;
r_books books%ROWTYPE;
BEGIN
FOR r_books IN books_cursor LOOP
DBMS_OUTPUT.PUT_LINE('Books title: '||r_books.title||' Retail price: '||r_books.retail);
END LOOP;
END;
• 示例说明 :在块的声明部分定义了 记录 r_books ,它具有 books 表的结构。可执行部分包含一个游标 FOR 循环,它 隐含打开 books_cursor 的游标,并将其内容 赋给 r_books 记录对名为 books_cursor 的游标中包含的每一行都执行一次这个游标 FOR 循环。这个循环中包含的唯一一个语句将显示当前正在处理的行。注意 :在 DBMS_OUTPUT 程序包显示的字符引用了记录中包含的列名称。因为将数据赋值给一个记录而不是单独的变量,所以显示值的唯一方法就是指定包含所需数据的列名称。在使用 %ROWTYPE 属性定义这个记录时,还为从 books 表中检索的各个值指定了列名称。要想指定应该显示哪一列或哪些列,必须在列名称之前添加包含数据的记录的名称,如 r_books.title在处理了 books_cursor 中包含的最后一行之后,这个循环将会终止,将隐含关闭游标。
BEGIN
FOR r_books IN (SELECT title,retail
FROM books NATURAL JOIN orderitems
WHERE order#=1012) LOOP
DBMS_OUTPUT.PUT_LINE('Books title: '||r_books.title||' Retail price: '||r_books.retail);
END LOOP;
END;
•修改示例,实现确定订单1012中购买的图书以及总应付款额。
DECLARE
v_ordertotal NUMBER(5,2):=0;
BEGIN
FOR r_books IN (SELECT title,retail,quantity
FROM books NATURAL JOIN orderitems
WHERE order#=1012) LOOP
DBMS_OUTPUT.PUT_LINE('Books title: '||r_books.title||' Retail price: '||r_books.retail);
v_ordertotal :=v_ordertotal + r_books.retail*r_books.quantity;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total Amount Due: '||v_ordertotal);
END;
带有逻辑运算符的游标循环控制
DECLARE
v_title books.title%TYPE;
v_retail books.retail%TYPE;
v_number NUMBER(2):=&How_Many_Books_To_Display;
CURSOR books_cursor IS
SELECT title,retail
FROM books
ORDER BY retail DESC;
BEGIN
OPEN books_cursor;
FETCH books_cursor INTO v_title,v_retail;
WHILE books_cursor%ROWCOUNT<=v_number AND
books_cursor%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(v_title||','||v_retail);
FETCH books_cursor INTO v_title,v_retail;
END LOOP;
CLOSE books_cursor;
END;
AND | TRUE | FALSE | NULL | OR | TRUE | FALSE | NULL |
TRUE | TRUE | FALSE | NULL | TRUE | TRUE | TRUE | TRUE |
FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | NULL |
NULL | NULL | FALSE | NULL | NULL | TRUE | NULL | NULL |
游标的使用——处理隐式游标
格式调用为: SQL%
注: INSERT, UPDATE, DELETE, SELECT 语句中不必明确定义游标。
隐式游标属性SQL %FOUND 布尔型属性 , 当最近一次读记录时成功返回,则值为 true ;SQL %NOTFOUND 布尔型属性 , 与 %found 相反;SQL %ROWCOUNT 数字型属性 , 返回已从游标中读取得记录数;SQL %ISOPEN 布尔型属性 , 取值总是 FALSE 。 SQL 命令执行完毕立即关闭隐式游标。
例:删除图书库存中某出版社出版的图书,如果不再存在该出版社的图书,则在出版设信息中删除该出版社信息.
DECLARE
v_pubid books.pubid%TYPE :=&in_pubid;
BEGIN
DELETE FROM books WHERE pubid=v_pubid;
DBMS_OUTPUT.PUT_LINE('删除出版社编号为'||v_pubid||'的图书记录');
COMMIT;
IF SQL%NOTFOUND THEN
DELETE FROM publisher WHERE pubid=v_pubid;
END IF;
COMMIT;
END;
练习
总结
本人从事软件项目开发20多年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂
讲师课堂链接:https://edu.csdn.net/lecturer/893