oracle-plsql笔记(游标)3

游标

游标相当于临时存储一个查询返回的多行数据,通过遍历游标可以逐行访问处理改结果的数据。
声明-打开-读取-关闭 四个步骤

语法

名称 语法
游标声明 游标名[(参数列表)] is 查询语句
游标打开 OPEN 游标名
游标取值 fetch 游标名 into 变量列表
游标关闭 CLOSE 游标名

游标的属性

游标属性 返回值类型 说明
%ROWCOUNT 整型 获得fetch语句返回的数据行数
%FOUNT 布尔型 最近的fetch语句返回1行数据为真,否则为假
%NOTFOUNT 布尔型 与上相反
%ISOPEN 布尔型 游标已经打开为真,否则为假
DECLARE 
    --声明游标
    CURSOR c_emp is select id,company from t_company;
    -- 声明接收游标数据的变量
    v_company t_company.company%type;
    v_id t_company.id%type;

BEGIN
    -- 打开游标
    OPEN c_emp;
    -- 遍历游标
    LOOP
        -- 获取游标数据
        FETCH c_emp into v_id, v_company;
        EXIT WHEN c_emp%NOTFOUND;
        dbms_output.put_line(v_company||'-'||v_id);
    END LOOP;

    -- 关闭游标
    CLOSE c_emp;
END;

带参数游标

就是在声明游标的时候做一个参数,然后打开游标时,传入实参。

DECLARE 
    --声明游标
    CURSOR c_emp(v_company_j t_company.company_j%type) is select id,company from t_company where company_j=v_company_j;
    -- 声明接收游标数据的变量
    v_company t_company.company%type;
    v_id t_company.id%type;

BEGIN
    -- 打开游标
    OPEN c_emp('abc');
    -- 遍历游标
    LOOP
        -- 获取游标数据
        FETCH c_emp into v_id, v_company;
        EXIT WHEN c_emp%NOTFOUND;
        dbms_output.put_line(v_company||'-'||v_id);
    END LOOP;

    -- 关闭游标
    CLOSE c_emp;
END;

for 循环写法

DECLARE 
-- 声明一个行级变量
v_emp_record emp%rowtype
--声明游标
cursor c_emp is select empno,ename from emp;
BEGIN
-- for循环让行级变量v_emp_record 在游标中循环
for v_emp_record in c_emp loop
  dbms.output.put_line(v_emp_record.empno||' '||v_emp_record.ename);
end loop;
END;

隐形游标

非查询语句,如更新删除,由Oracle系统自动创建,自动完成 ,存放的数据与用户自定义的显示游标无关的,最新一条sql语句所包含的数据。游标名为sql。
调用方式:sql%游标属性名。

案例1

DECLARE
BEGIN
  update emp set ename='new' where  empno='7788';
  if sql%notfound then
    dbms.output.put_line('没有找到数据');
elsif sql%found then
     dbms.output.put_line('sql%rowcount');
  end if;
END;

案例2

删除部门表中名称重复的记录,保留最后一次添加的部门,ID最大。

DECLARE
  -- CURSOR cur_delnames is select  * from dept group by dname;
BEGIN
-- 隐形游标 
delete from dept where deptno not in
(
  select max(deptno) from dept group by dname
);
if sql%found then 
  dbms.output.put_line('删除'|sql%count|'条数据');
commit;
end if;
END;

动态sql

plsql内部正常运行DML(insert,delete,update),DQL(select, into )。
如果去运行DDL(create,truncate,drop)需要动态sql来执行。
动态sql不但可以在plsql中运行DDL,也可以运行DML,DQL
动态sql语法结构
execute immediate 'sql语句' [into 变量][using 绑定参数]

案例1

--动态sql DDL语句
declare
v_sql varchar2(255):='create table a (id number primary key ,name varchar2(30) not null)';
begin
-- 执行创建表
execute immediate v_sql;
--执行删除表中所有数据操作
--execute immediate 'truncate table a';  

end;

案例2

动态sql执行DML语句增删改

BEGIN
execute immediate 'insert into a(id,name) values(1,''张三'')';
-- 张三是两个单引号,其中一个单引号是转义符号。
-- 转义符当字段过多时不好写,可以采用占位参数的方式
execute immediate 'insert into a(id,name) values(:1,:2)' using 2,'李四';
END;

案例3

执行DQL语句

DECLARE
  v_ename emp.ename%type;
  v_deptno emp.deptno%type;
  v_sale emp.sale%type;
BEGIN
execute immediate 'select ename,deptno,sale into v_ename,v_deptno,v_sale  from emp where sal> :sal and deptno= :deptno' using 2000,10 ;
dbms_output.put_line(v_ename||v_sale||v_emp.deptno)
-- 其中:sal 和:deptno都是占位参数,后面接using 
END;

select into 变量不能返回多行,所以当选择多行数据时会报错。

动态游标

显性游标加上动态sql就是动态游标。

DECLARE
-- 声明动态游标类型
type refcur is ref cursor;
-- 定义动态游标变量
v_cur refcur;
v_emp emp%rowtype;

BEGIN
open v_cur for 'select * from emp where sal >:sal'   using   3000;  
loop
fetch v_cur into v_emp;
exit when v_cur%notfound;
dbms_output.put_line(v_emp.empno||','||v_emp.ename);
end loop;
close v_cur;
END;

动态游标无法传入参数。

自定义记录型

--自定义记录型
declare
 type mytype is record(x number(4), y varchar2(10));
 mt mytype;
 cursor mysur is
 select 1, '张三' from dual
 union
 select 2, '李四' from dual
 union
 select 3, '王五' from dual;
begin
 open mysur;
 loop
  fetch mysur into mt;
 
  exit when mysur%notfound;
  dbms_output.put_line(mt.x || ',' || mt.y);
 end loop;
 close mysur;    
end;
image.png

异常处理

用于处理程序中产生错误信息导致整个程序终止的代码,用EXCEPTION来处理,使程序能够继续执行。
declare begin 程序块; exception 错误信息处理; end;

错误号 异常名称 说明
ora-1403 NO_DATA_FOUND SELECT INTO 没有找到数据
ora-1422 TOO_MANY_ROWS SELECT INTO 返回多行
ora-1476 ZERO_DIVIDE 0是被除数
ora-1722 INVALID_NUMBER 转换数字错误
DECLARE
v_x int;
BEGIN
dbms.output.put_line('begin执行开始');
--这里报错无效数字
SELECT empno from emp into v_x where empno=1000;
dbms.output.put_line('begin执行结束');
-- 异常处理部分
EXCEPTION
  when no_data_found then 
    dbms.output.put_line('没有这个ID');
--假如还有其他错误,也可以把上面的注释掉,直接使用others 代表所有错误。
WHEN OTHERS THEN
  dbms.output.put_line('其他错误');
END;

上一篇:控制流语句
下一篇:存储过程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容

  • 游标(cursor) 游标能够根据查询条件从数据表中提取一组记录,将其作为一个临时表置于数据缓冲区中,利用指针逐行...
    程序小小鸡阅读 717评论 0 0
  • 2019-05-13 游标(cursor)能够根据查询条件从数据表中提取一组记录,将其作为一个临时表置于数据缓冲区...
    Mr_J316阅读 4,127评论 0 0
  • 1、Check规则 Check (Agebetween15and30 )把年龄限制在15~30岁之间 2、新SQL...
    姜海涛阅读 826评论 0 4
  • 游标概念使用游标可以让用户像操作数组一样操作查询出来数据结果集,它提供了一种从集合性质的结果中提取单条记录的手段。...
    乘风破浪的姐姐阅读 2,312评论 0 1
  • 1.1 基本结构 PL/SQL程序由三个块组成,即声明部分、执行部分、异常处理部分。 1.2 命名规则 1.3 记...
    慢清尘阅读 3,850评论 3 14