六、Oracle SQL(游标&RECORD&存过、游标、RECORD整合)
8. 游标
8.1 简介
8.1.1 定义
实质上是数据集,类似数组一样,把查询的数据集存储在内存当中。
使用时可以通过游标指向其中一条记录,也可以通过循环游标达到循环数据集的目的。
8.1.2 游标的种类
-
显式游标:使用之前必须得先声明定义,一般是对查询语句的结果进行定义游标。
可以通过游标循环获取结果集内的记录,也可以根据业务需求跳出循环结束游标的获取。
循环完成后,可以通过关闭游标,结果集就不能再获取了。全部操作完全由开发者自己编写完成,自己控制。 -
隐式游标:指的是PL/SQL自己管理的游标,开发者不能自己控制操作,只能获得它的属性信息。
8.2 显式游标
显式游标在实际开发中经常使用到,可以丰富PL/SQL的开发程序的编写,实现一些循环类的复杂业务。游标的使用步骤如下:
--1.声明游标:
声明游标指的是给游标命名并给游标关联一个查询结果集
cursor 游标名
is 查询语句
--2.打开游标:
初始化游标指针
PS:游标一旦打开后,游标对应的结果集就是静态不会再变了,不管查询的表的基础数据发生了变化。
open 游标名;
--3.读取游标中数据:
通过fetch into语句完成,把当前游标指针指向的数据行读取到对应的变量中(声明的record变量)。
PS:游标读取一般和循环LOOP一起使用,用于循环获取数据集中的记录。
fetch 游标名 into 声明的record变量
--4、关闭游标:
关闭后,该游标关联的结果集就释放了,不能够再操作了
PS:游标使用完,一定要关闭游标释放资源。
close 游标名;
8.2.1显式游标的属性
我们利用显式游标的属性值来获取游标所处的状态,然后对应做相应的处理,常用的属性有四个:
-
%NOTFOUND 表示游标获取数据的时候是否有数据提取出来,没有数据返回TRUE,有数据返回false,经常被用来判断游标是否全部循环完毕。
-
%FOUND 正好和%NOTFOUND相反,当游标提取数据值时有值,返回TRUE,否则返回FALSE。
-
%ISOPEN 用来判断游标是否打开。
-
%ROWCOUNT 表示当前游标FETCH INTO获取了多少行的记录值,用来做计数用的。
例子:创建一个游标循环打印学生信息表中学生基本信息,代码如下:
--定义游标
declare cursor cur_xsjbxx
is select * from stuinfo order by stuid;
--定义记录变量 rowtype:用于接受一行数据
ls_curinfo cur_xsjbxx%rowtype;
begin
--打开游标
open cur_xsjbxx;
--循环
loop
--获取记录值并写入计入变量
fetch cur_xsjbxx into ls_curinfo;
--当没有数据时不再获取(%NOTFOUND用来判断游标是否全部循环完毕。)
exit when cur_xsjbxx%notfound;
--PL/sql中输出信息(相当与java中的System.out.println())
dbms_output.put_line('学号:' || ls_curinfo.stuid || ',姓名:' || ls_curinfo.stuname);
end loop;
--关闭游标
close cur_xsjbxx;
end;
8.3 隐式游标
-
隐式游标虽然不能像显式游标一样具有操作性,但是在实际开发过程当中还是经常使用到它的属性值。
-
隐式游标主要是用在select语句或一些dml操作语句时,PL/SQL程序会自动打开隐式游标,这个隐式游标是不受开发者控制的。
-
oracle隐式游标没有像显式游标一样声明游标名,而是直接采用“SQL”或“sql”作为隐式游标的名称。
-
显式游标表示的属性值都是对结果集行数的一些判断,而隐式游标对应的就是DML语句影响的行数。
--隐式游标
declare
--只定义记录变量,没有声明游标(如果一个表有较多的列,使用%rowtype来定义一个表示表中一行记录的变量)
ls_xsjbxx stuinfo%rowtype;
begin
--查询学生信息(select * into把整个表数据设置进定义的记录变量中,用变量来实现游标功能)
select * into ls_xsjbxx from stuinfo t where t.stuid = 'SC201801001';
if sql%found then
dbms_output.put_line('学号:' || ls_xsjbxx.stuid || ',姓名:' || ls_xsjbxx.stuname);
end if;
--查询学生信息(不存在的学生)
select * into ls_xsjbxx from stuinfo t where t.stuid = 'SC201901001';
if sql%found then
dbms_output.put_line('学号:' || ls_xsjbxx.stuid || ',姓名:' || ls_xsjbxx.stuname);
end if;
exception
when no_data_found then
dbms_output.put_line('该学生SC201901001不存在');
end;
9. RECORD(自定义结构)
9.1 定义
记录数据类型的一种,将几个相关的、分离的、基本数据类型的变量组成一个类似于整体表结构的对象,即RECORD复合数据类型。
在使用记录数据类型变量时,需要在声明部分先定义记录的组成、记录的变量,然后在执行部分引用该记录变量本身或其中的成员。
RECORD数据类型常用于存过与游标结合使用时,用于记录数据。
9.2 格式
/**
格式:
TYPE 名称(随便起)IS RECORD(
列1名称 列1类型,
列2名称 列2类型
);
*/
TYPE T_RECORD IS RECORD (
GOODS_CODE VARCHAR2(64),
GOODS_NAME VARCHAR2(64),
ORDER_NUM VARCHAR2(16),
DIS_ORDER_NUM VARCHAR2(16),
TOTAL_ORDER_NUM VARCHAR2(16),
);
10. 存过、游标、RECORD整合
10.1 代码
/*1.定义存过*/
CREATE OR REPLACE
PROCEDURE PRO_RE_USER_ORD_GOODS(
--NOW_DATE格式:YYYYMMDD 如:20190801(此时统计的是2019年7月31日的数据)
NOW_DATE IN VARCHAR2
)
IS
/*2.定义变量 START*/
--定义RECORD型记录类型;
TYPE T_RECORD IS RECORD (
GOODS_CODE VARCHAR2 (64),
GOODS_NAME VARCHAR2 (64)
) ;
--定义返回结果集接收的变量,类型为T_RECORD;
PS:这里也可以不用record,直接指定V_ROWRESUT为%rowtype类型
V_ROWRESUT T_RECORD ;
--定义主键
PID VARCHAR2 (256) ;
/*2.定义变量 end*/
/*3.定义游标,执行查询结果集操作 START*/
CURSOR CUR_RE_USER_ORD_GOODS
IS
--查询语句开始
SELECT
A .GOODS_CODE,
B.GOODS_NAME
FROM
(
SELECT
ORD.GOODS_CODE
FROM
ORDER_INFO ORD
GROUP BY
ORD.GOODS_CODE
) A
LEFT JOIN GOODS_INFO B ON A .GOODS_CODE = B.GOODS_CODE ;
--查询语句结束
/*3.定义游标,执行查询结果集操作 END*/
/*4.打开并循环游标,进行数据操作 START*/
BEGIN
OPEN CUR_RE_USER_ORD_GOODS; --打开游标;
LOOP --开始执行循环,遍历查询结果集表;
FETCH CUR_RE_USER_ORD_GOODS INTO V_ROWRESUT; --循环游标并赋值给结构体变量;
EXIT WHEN CUR_RE_USER_ORD_GOODS %NOTFOUND; --如果游标遍历完成,就退出循环;
--获取 UUID 并赋值给 PID 变量;
SELECT SYS_GUID() INTO PID FROM DUAL;
--插入“订购商品记录表” 开始
INSERT INTO RE_USER_ORD_GOODS (
ID,
GOODS_CODE,
GOODS_NAME,
CREATE_TIME
)VALUES(
PID,
V_ROWRESUT.GOODS_CODE,
V_ROWRESUT.GOODS_NAME,
SYSDATE
);
--插入“订购商品记录表” 结束
END LOOP; --结束循环;
CLOSE CUR_RE_USER_ORD_GOODS; --关闭游标;
COMMIT; --提交 INSERT 操作;
END;
/*4.打开并循环游标,进行数据操作 END*/
10.2 oracle存储过程中is和as区别
在存储过程(PROCEDURE)和函数(FUNCTION)中没有区别;
在视图(VIEW)中只能用AS不能用IS;
在游标(CURSOR)中只能用IS不能用AS。
10.3 声明变量的方式
v_temp varchar(10)
v_temp tablename.property%type(表名属性名%type,指的是一个表中某个字段的类型,这样可以灵活使用)
v_stu student%rowtype;(这种类型就是定义一个变量,这个变量的类型为一个表数据的行类型,用于接收查询的一整行数据)
10.4 赋值方式
:=
转载自:有梦想的肥宅