引言:PLSQL数据类型
标量数据类型:数字类、字符类、日期类、布尔类(boolean)、
复合数据类型:记录(%rowtype)、表、数组
引用类型:REF CURSOR
LOB类型:BLOB、CLOB

1.系统定义的记录:%rowtype
使用%rowtype属性定义记录变量:可以基于表或视图定义记录变量
当使用%ROWTYPE属性定义记录变量时,记录成员个数,名称,类型与表或视图列的个数,
名称,类型完全相同.

1.1 在select语句中使用PL/SQL记录
declare
v_emp emp%rowtype;
begin
select * into v_emp from emp where empno=7788;
dbms_output.put_line(v_emp.ename);
end;

1.2 在insert语句中使用PL/SQL记录
declare
dept_record dept%rowtype;
begin
dept_record.deptno:=50;
dept_record.dname:='administrator';
dept_record.loc:='beijing';
insert into dept values dept_record;
end;

1.3 在insert语句VALUES子句中使用记录成员
declare
dept_record dept%rowtype;
begin
dept_record.deptno:=60;
dept_record.dname:='sales';
insert into dept (deptno,dname) values
(dept_record.deptno,dept_record.dname);
end;

1.4在UPDATE语句中使用PL/SQL记录
在SET子句中使用记录变量
declare
dept_record dept%rowtype;
begin
dept_record.deptno:=60;
dept_record.dname:='sales';
dept_record.loc:='shanghai';
update dept set row=dept_record where deptno=60;
end;

在SET子句中使用记录成员
declare
dept_record dept%rowtype;
begin
dept_record.loc:='guangzhou';
update dept set loc=dept_record.loc where deptno=10;
end;

1.5在DELETE语句中使用PL/SQL记录:只能在DELETE语句中的WHERE子句中使用记录成员
declare
dept_record dept%rowtype;
begin
dept_record.deptno:=50;
delete from dept where deptno=dept_record.deptno;
end;

2.用户自定义记录
首先定义类型,在声明该类型的变量。
2.1 定义记录类型
declare
type emp_record_type is record(
name emp.ename%type,
salary emp.sal%type,
dno emp.deptno%type);
begin
null;
end;

语法:
type 记录类型名 is record(
属性名 数据类型,
...
);
2.2 定义记录类型变量
emp_record emp_record_type;
语法:
变量名 记录类型名;
declare
--自定义类型emp_record_type
type emp_record_type is record(
ename emp.ename%type,
sal emp.sal%type);
--定义变量,变量的类型是emp_record_type
emp_record emp_record_type;
begin
--变量赋值
select ename,sal into emp_record from emp where empno=&no;
dbms_output.put_line(emp_record.ename||' '||emp_record.sal);
end;

2.3 在select into 语句中使用自定义记录
--set serveroutput on
declare
type emp_record_type is record(
name emp.ename%type,
salary emp.sal%type,
dno emp.deptno%type);
emp_record emp_record_type;
begin
select ename,sal,deptno into emp_record from emp where empno=&no;
dbms_output.put_line(emp_record.name);
end;

2.4 在select into 语句中使用记录成员
declare
type emp_record_type is record(
name emp.ename%type,
salary emp.sal%type,
dna emp.deptno%type);
emp_record emp_record_type;
begin
select ename,sal into emp_record.name,emp_record.salary
from emp where empno=&no;
dbms_output.put_line(emp_record.name);
end;

3.游标
当在PL/SQL块中执行查询语句SELECT和数据操纵语句DML时,
ORACLE会为其分配上下文区(CONTEXT AREA),游标是指向上下文区的指针。
对于数据操纵语句和单行SELECT INTO语句来说,ORACLE会为他们分配隐含游标。
使用显示游标处理多行数据。
3.1 显示游标操作
3.1.1 定义游标
语法:cursor cursor_name is 子查询;
例1:
declare
cursor cursor_emp is select * from emp;
begin
dbms_output.put_line('定义了一个游标');
end;

3.1.2 打开游标:
执行对应的SELECT语句并将SELECT语句的结果暂时存放到结果集中.
语法:open cursor_name;
例2:
declare
cursor cursor_emp is select * from emp;
begin
open cursor_emp;
dbms_output.put_line('打开了一个游标');
end;

3.1.3 提取数据
打开游标后,SELECT语句的结果被临时存放到游标结果集中,
使用FETCH语句只能提取一行数据
语法:fetch cursor_name into variable1,varibale2,...;
例3:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
v_counter number:=1;
begin
open cursor_emp;
loop
fetch cursor_emp into v_emp;
dbms_output.put_line('提取一行数据'||v_emp.ename);
v_counter:=v_counter+1;
if v_counter>20 then
exit;
end if;
end loop;
end;

3.1.4 关闭游标
语法:close cursor_name;
例4:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
v_counter number:=1;
begin
open cursor_emp;
loop
fetch cursor_emp into v_emp;
dbms_output.put_line('提取一行数据'||v_emp.ename);
v_counter:=v_counter+1;
if v_counter>20 then
exit;
end if;
end loop;
close cursor_emp;
end;

3.2 显示游标属性
用于返回显示游标的执行信息,包括%isopen,%found,%notfound,%rowcount
3.2.1 %isopen:确定游标是否打开
语法:
if cl%isopen then
...
else
open c1;
end if;
例5:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
v_counter number:=1;
begin
if cursor_emp%isopen then
null;
else
open cursor_emp;
end if;
loop
fetch cursor_emp into v_emp;
dbms_output.put_line('提取一行数据'||v_emp.ename);
v_counter:=v_counter+1;
if v_counter>20 then
exit;
end if;
end loop;
close cursor_emp;
end;

3.2.2 %found:检查是否从结果集中提取到了数据
语法:
loop
fetch c1 into var1,var2;
if c1%found then ... else exit;
end loop;
例6:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
open cursor_emp;
loop
fetch cursor_emp into v_emp;
if cursor_emp%found then
dbms_output.put_line('提取一行数据'||v_emp.ename);
else
exit;
end if;
end loop;
close cursor_emp;
end;

3.2.3 %notfound 检查是否从结果集中提取不到数据
语法:
loop
fetch c1 into var1,var2;
exit when c1%notfound;
...
end loop;
例7:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
open cursor_emp;
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line('提取一行数据'||v_emp.ename);
end loop;
close cursor_emp;
end;

3.2.4 %rowcount:返回到当前行 为止已经提取到的实际行数
语法:
loop
v_1:=cursor_name%rowcount;
end loop;

例8:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
if not cursor_emp%isopen then
open cursor_emp;
end if;
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line('第'||cursor_emp%rowcount||'个雇员: '
||v_emp.ename);
end loop;
close cursor_emp;
end;
例9:
declare
cursor cursor_emp is select * from emp;
v_emp emp%rowtype;
begin
if not cursor_emp%isopen then
open cursor_emp;
end if;
loop
fetch cursor_emp into v_emp;
exit when cursor_emp%notfound;
dbms_output.put_line('提取一行数据'||v_emp.ename);
end loop;
dbms_output.put_line('游标总行数'||cursor_emp%rowcount);
close cursor_emp;
end;

3.3基于游标定义记录变量
例10:
declare
cursor emp_cursor is select ename,sal from emp;
emp_record emp_cursor%rowtype;
begin
open emp_cursor;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('雇员名:'||emp_record.ename
||',雇员工资:'||emp_record.sal);
end loop;
close emp_cursor;
end;

3.4参数游标
定义参数游标时,游标参数只能指定数据类型,而不能指定长度.
语法:cursor cursor_name(parameter_name datatype) is select_statment;
例11:
declare
cursor emp_cursor(no number) is select ename from emp where deptno=no;
v_ename emp.ename%type;
begin
open emp_cursor(&no);
loop
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename);
end loop;
close emp_cursor;
end;
例11-2:字符参数
declare
cursor emp_cursor(p_job varchar2) is select ename from emp where job=p_job;
v_ename emp.ename%type;
begin
open emp_cursor('&p_job');
loop
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename);
end loop;
close emp_cursor;
end;
例11-3:两个参数
declare
cursor emp_cursor(p_no number,p_job varchar2) is
select ename from emp where deptno=p_no and job=p_job;
v_ename emp.ename%type;
begin
open emp_cursor(&p_no,'&p_job');
loop
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename);
end loop;
close emp_cursor;
end;
--30 SALESMAN

begin
for rs in (select ename from emp where deptno=&no and job='&job') loop
dbms_output.put_line(rs.ename);
end loop;
end;

3.5 使用游标更新或删除数据
要通过游标更新或删除数据,在定义游标时必须要带有FOR UPDATE子句。
语法:
cursor cursor_name(parameter_name datetype) is
select_statement for update;
for update子句用于在游标结果集数据上加锁,防止其他用户在相应行执行DML操作。
使用游标更新或删除数据时,
可以在UPDATE后DELETE语句中引用WHERE CURRENT OF子句。
语法:
update table_name set 列名=值 where current of cursor_name;
delete table_name where current of cursor_name;
3.5.1 使用游标更新数据
例12:
declare
cursor emp_cursor is select ename,sal from emp for update;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal;
exit when emp_cursor%notfound;
if v_sal<2000 then
update emp set sal=sal+100 where current of emp_cursor;
dbms_output.put_line(v_ename||'工资增加100');
end if;
end loop;
close emp_cursor;
end;
例12-2:
declare
cursor emp_cursor is select ename,sal from emp;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal;
exit when emp_cursor%notfound;
if v_sal<2000 then
update emp set sal=sal+100 where ename=v_ename;
dbms_output.put_line(v_ename||'工资增加100');
end if;
end loop;
close emp_cursor;
end;

3.5.2 使用游标删除数据
例13:
declare
cursor emp_cursor is select ename,sal,deptno from emp for update;
v_ename emp.ename%type;
v_sal emp.sal%type;
v_deptno emp.deptno%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal,v_deptno;
exit when emp_cursor%notfound;
if v_deptno=30 then
delete from emp where current of emp_cursor;
dbms_output.put_line(v_ename||'被删除了');
end if;
end loop;
close emp_cursor;
end;
例13-2:
declare
cursor emp_cursor is select ename,sal,deptno from emp;
v_ename emp.ename%type;
v_sal emp.sal%type;
v_deptno emp.deptno%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal,v_deptno;
exit when emp_cursor%notfound;
if v_deptno=30 then
delete from emp where ename=v_ename;
dbms_output.put_line(v_ename||'被删除了');
end if;
end loop;
close emp_cursor;
end;

3.6 游标FOR循环
使用FOR循环时,ORACLE会隐含的打开游标,提取游标数据并关闭游标
语法:
for record_name in cursor_name loop
statement1;
statement2;
...
end loop;
每循环一次提取一次数据,在提取了所有数据后,自动退出循环并隐含的关闭游标
3.6.1 使用游标FOR循环
例14:
declare
cursor emp_cursor is select ename,sal from emp;
begin
for emp_record in emp_cursor loop
dbms_output.put_line('第'||emp_cursor%rowcount||'个雇员: '
||emp_record.ename);
end loop;
end;

3.6.2 在游标FOR循环中直接使用子查询
例15:
declare
i number:=1;
begin
for rs in (select ename,sal from emp) loop
dbms_output.put_line('第'||i||'个雇员: '||rs.ename);
i:=i+1;
end loop;
end;

3.7 使用游标变量
PL/SQL的游标变量中存放着指向内存地址的指针.
3.7.1 游标变量使用步骤
包括定义游标变量,打开游标,提取游标数据,关闭游标等四个阶段
1)定义ref cursor类型和游标变量
type ref_type_name is ref cursor [return return_type];
cursor_varibale ref_type_name;
当指定RETURN子句时,其数据类型必须是记录类型,不能在包内定义游标变量
2)打开游标
open cursor_variable for select_statement;
3)提取游标数据
fetch cursor_varibale into variable1,variable2,...;
4)关闭游标变量
close cursor_varibale;

3.7.2 游标变量使用示例
1)在定义REF CURSOR类型时不指定RETURN子句
在打开游标时可以指定任何的SELECT语句
例16:
declare
type emp_cursor_type is ref cursor;
emp_cursor emp_cursor_type;
emp_record emp%rowtype;
begin
open emp_cursor for select * from emp where deptno=10;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('第'||emp_cursor%rowcount||'个雇员: '||emp_record.ename);
end loop;
close emp_cursor;
end;

2)在定义REF CURSOR类型时指定RETURN子句
在打开游标时SELECT语句的返回结果必须与RETURN子句所指定的记录类型相匹配.
例17:
declare
type emp_record_type is record(ename varchar2(10),salary number(6,2));
type emp_cursor_type is ref cursor return emp_record_type;
emp_cursor emp_cursor_type;
emp_record emp_record_type;
begin
open emp_cursor for select ename,sal from emp where deptno=20;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line('第'||emp_cursor%rowcount||'个雇员: '
||emp_record.ename);
end loop;
close emp_cursor;
end;

3.8 使用CURSOR表达式
CURSOR表达式用于返回嵌套游标
结果集不仅可以包含普通数据,而且允许包含嵌套游标的数据
语法:cursor(subquery)
例18:
declare
type refcursor is ref cursor;
cursor dept_cursor(no number) is
select a.dname,
cursor(select ename,sal from emp where deptno=a.deptno)
from dept a where a.deptno=no;
empcur refcursor;
v_dname dept.dname%type;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open dept_cursor(&no);
loop
fetch dept_cursor into v_dname,empcur;
exit when dept_cursor%notfound;
dbms_output.put_line('部门名:'||v_dname);
loop
fetch empcur into v_ename,v_sal;
exit when empcur%notfound;
dbms_output.put_line('雇员名:'||v_ename||',工资:'||v_sal);
end loop;
end loop;
close dept_cursor;
end;

例19:
begin
for rs in (select dname,deptno from dept where deptno=&no) loop
dbms_output.put_line('部门名:'||rs.dname);
for rs2 in (select ename,sal from emp where deptno=rs.deptno) loop
dbms_output.put_line('雇员名:'||rs2.ename||',工资:'||rs2.sal);
end loop;
end loop;
end;

Oracle_PL/SQL(3) 游标的更多相关文章

  1. SQL Server 游标运用:鼠标轨迹字符串分割

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 游标模板(Cursor Template) 鼠标轨迹字符串分割SQL脚本实现(SQL Code ...

  2. sql server 游标的简单用法

    sql server游标: --定义游标 declare cursor1 cursor for select ID,Name from A --打开游标 open cursor1 declare @i ...

  3. MySQL通过视图(或临时表)实现动态SQL(游标)

    >参考de优秀文章 写MySQL存储过程实现动态执行SQL Dynamic cursor in stored procedure MySQL通过视图(或临时表)实现动态SQL(游标). 因在实现 ...

  4. (2.14)Mysql之SQL基础——游标

    (2.14)Mysql之SQL基础——游标 关键词:Mysql游标 -- (1)定义游标 declare cur_name cursor for select * from table_name wh ...

  5. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...

  6. SQL Server 游标的应用

    ----------------SQL游标应用----------------- 今天由于业务需求,需要在存储过程中实现有一个表的主键去匹配在另一个表中作为外键所对应的数值 ,若在C#中则非常简单只需 ...

  7. SQL Server游标 C# DataTable.Select() 筛选数据 什么是SQL游标? SQL Server数据类型转换方法 LinQ是什么? SQL Server 分页方法汇总

    SQL Server游标   转载自:http://www.cnblogs.com/knowledgesea/p/3699851.html. 什么是游标 结果集,结果集就是select查询之后返回的所 ...

  8. SQL Server 游标运用:查看所有数据库所有表大小信息(Sizes of All Tables in All Database)

    原文:SQL Server 游标运用:查看所有数据库所有表大小信息(Sizes of All Tables in All Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容 ...

  9. SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)

    原文:SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容(C ...

随机推荐

  1. ArcGIS案例学习笔记3_1_地理配准案例_目视找点

    ArcGIS案例学习笔记3_1_地理配准案例_目视找点 计划时间:第3天上午 方法:地理配准/添加链接点/左键/右键/输入坐标 数据:江苏省.zip 矢量:省界,市界,GPS WGS84 地理坐标系 ...

  2. 传输层——UDP报文头介绍

    16位源端口 16位目的端口 16位总长度 16位校验和 数据 源端口:长度为16位,2个字节. 目的端口:长度为16位,2个字节. 总长度:长度为16位,2个字节,表示 UDP包头长度 和 数据长度 ...

  3. 3DMAX 批量 场景 对象 导出 .X格式 脚本

    一.首先你需要下载一个 Total Commader文件管理软件.利用这个软件你可以收集文件夹下包含子文件夹下的max文件(或完整路径)打开TotalCMD后使用查找文件:(如图红框中的操作)1. 2 ...

  4. C# 监测每个方法的执行次数和占用时间(测试1)

    在Nuget引用 Castle.DynamicProxy 和 Newtonsoft.Json 这个 原文:http://www.cnblogs.com/RicCC/archive/2010/03/15 ...

  5. vue watch详细用法

    在vue中,使用watch来响应数据的变化.watch的用法大致有三种.下面代码是watch的一种简单的用法 html: <input type="text" v-model ...

  6. javascript中scrollTop和offsetTop的区别

    scrollTop是指某个可滚动区块向下滚动的距离,offsetTop则是元素的上边框与父元素的上边框的绝对距离. 1.offsetTop   : 当前对象到其上级层顶部的距离. 不能对其进行赋值.设 ...

  7. linux 系统 网卡 ethX没有显示IP的处理方式

    1 临时方式 ifconfig  设备名 IP 地址 (ifconfig eth0  192.168.1.117) 设置好之后马上生效,不需要重启网卡服务(千万别重启网卡服务,不然刚刚设置的又没有了) ...

  8. Map、Set、List 集合 差别 联系

    提到集合之前,先说说数组Array和集合的区别:   (1)数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型)   (2)JAVA集合可以存储和操作数目不固定的一组数据. ( ...

  9. Spring-data-redis redis

    什么是spring-data-redis spring-data-redis是spring-data模块的一部分,专门用来支持在spring管理项目对redis的操作,使用java操作redis最常用 ...

  10. sql去除重复语句

    转自芙蓉清秀的BLOG http://blog.sina.com.cn/liurongxiu1211  sql去除重复语句 (2012-06-15 15:00:01) sql 单表/多表查询去除重复记 ...