游标和动态SQL

游标和动态SQL游标类别:静态游标(指在编译的时候,游标就与一个select语句进行了静态绑定的游标,这种游标只能作用于一个查询语句)和动态游标(就是希望我们的查询语句在运行的时候才跟游标绑定,为了使用动态游标,必须声明游标变量)。动态游标分两种,分别是强类型和弱类型。强类型的动态游标只能支持查询结果与他类型匹配的这种查询语句,弱类型的动态游标可以支持任何的查询语句。静态游标分为两种,隐式游标和显

大家好,又见面了,我是你们的朋友全栈君。

游标类别:静态游标(指在编译的时候,游标就与一个select语句进行了静态绑定的游标,这种游标只能作用于一个查询语句)和动态游标(就是希望我们的查询语句在运行的时候才跟游标绑定,为了使用动态游标,必须声明游标变量)。

动态游标分两种,分别是强类型和弱类型。强类型的动态游标只能支持查询结果与他类型匹配的这种查询语句,弱类型的动态游标可以支持任何的查询语句。

静态游标分为两种,隐式游标和显示游标。显示游标是有用户声明和操作的一种游标。隐式游标是Oracle为所有的数据操作语句自动声明的一种游标。

在每个用户的会话中,我们可以同时打开多个游标,这个数量有数据库初始化参数文件中的OPEN CURSORS这个参数来定义。

显示游标的用法步骤:

1、声明显式游标,语法:CURSOR<游标名>ISSELECT<语句>;

在声明游标的时候通常还要声明一些变量用来存放查询语句产生的查询结果。声明游标和变量都在declare中的。通常先声明变量,在声明游标。

2、打开游标,从打开游标开始,后面的步骤都是在beginend中执行的。语法:open<游标名>;当打开游标后查询语句就开始执行了,查询结果放到Oracle的缓冲区中,然后游标指向了这个缓冲区中查询结果的第一行记录之前。

3、提取游标,通过提取游标,游标依次指向查询结果的每一行。语法:FETCH<游标名>INTO<变量列表>;

4、关闭游标,语法:CLOSE<游标名>;

示例:

declare
 name varchar2(50);                               --定义变量存储employees表中的内容。
 department_name varchar2(20);               --定义变量存储departments表中的内容;
 cursor emp_cur IS                               --定义游标emp_cur
select name,department_name               --选出所有员工的姓名和所做部门。
from employees e,departments d
  where e.department_id=d.department_id;
begin
 open emp_cur;                                      --打开游标
 LOOP
 FETCH emp_cur INTO name,depart_name;      --将第一行数据放入变量中,游标后移。
      EXIT WHEN emp_cur%NOTFOUND;
      dbms_output.put_line(name||’在’||department_name);
 END LOOP;
 CLOSE emp_cur;
END;

游标的属性:%ISOPEN,游标是否打开;%FOUND,游标是否指向有效行;%NOTFOUND,游标是否没有指向有效行;%ROWCOUNT,游标抽取过的行数。

语法:游标名%属性名。

例如:公司上市,决定给员工提高薪资,入职时间超过1年涨1001000元封顶。

declare
 hire_date date;              --存放员工入职日期
 e_id number;                   --存放员工id
 cursor emp_cur is            --定义游标
      select id,hire_date from employees;
begin
 open emp_cur;                 --打开游标
 loop
      fetch emp_cur into e_id,hire_date       --将数据逐条存入变量
      exit when emp_cur%NOTFOUND;
      if 100*(2014-to_char(hire_date,’yyyy’))<1000 then
             update salary setsalaryvalue=salaryvalue+100*(2010-to_char(hire_date,’yyyy’)) where employee.id=e_id;
      else
             update salary setsalaryvalue=salaryvalue+1000 where employee.id=e_id;
      end if;
 end loop;
      close emp_cur;
end

使用循环游标游标的读取,语法:FOR <类型> IN <游标名>LOOP –操作各行数据 END LOOP;

DECLARE
      CURSOR emp_cur IS
      SELECT name,department_name
      FROM employees e,departments d;
      WHERE e.department_id=d.department_id;
BEGIN
      FOR employ_record IN emp_cur LOOP
             dnms_output.put_line(employ_record.name||’在’||employee_record.department_name);
      END LOOP;
END;

隐式游标

隐式游标与显示游标的区别:1、不用声明游标。2、不用打开和关闭游标。3、必须使用INTO子句,结果只能是一条。

隐式游标与显示游标的相同的:有相同的属性,隐式游标使用属性的方法是在属性名前面加上SQL%,即SQL%FOUNDSQL%ISOPEN等。

DECLARE
      name VARCHAR2(50);
      department_name varchar(20);
BEGIN
      SELECT name,department_name
      INTO name,deprtment_name
      FROM employees e,departments d;
      WHERE e.department_id=d.department_id and e.id=1;
      dbms_output.put_line(name||’在’||department_name);
END;

因为隐式游标查询结果只有一行,所以如果用来计数没有多大的意义,所以%ROECOUNT这个属性经常用来判断插入、删除、更新是否成功,但是要在COMMIT语句之前。如果在COMMIT之后,%ROECOUNT只能是0

begin
      update employees set name=name||’A’
      where id=7;
      if sql%rowcount=1 then
             dbms_output.put_line(‘表已更新!’);
      else
             dbms_output.put_line(‘编号未找到’);
      end if;
end;

REF动态游标

ref动态游标可以在运行的时候与不同的语句进行关联,他是动态的。ref动态游标被用于处理多行的查询结果集,ref动态游标是ref类型的变量,类似于指针。

定义ref动态游标类型:type<类型名> is ref cursor return <返回类型>;

声明ref动态游标:<游标名> <类型名>;

打开ref动态游标:OPEN<游标名> FOR <查询语句>;

示例:

DECLARE
      TYPE refcur_t IS REF CURSOR
      RETURN employess%ROWTYPE;
      refcur refcur_t;
      v_emp employees%ROWTYPE;
BEGIN
      OPEN refcur FOR
      SELECT * FROM employees;
      LOOP
             FETCH refcur INTO v_emp;
             EXIT WHEN refcur%NOTFOUND;
             dbms_output.put_line(refcur%ROWCOUNT||’‘||v_emp.name);
      END LOOP;
      CLOSE refcur;
END;

强类型ref动态游标:带有RETURN语句的REF动态游标。

弱类型ref动态游标:不带有RETURN语句的REF动态游标。

例如:

DECLARE
      TYPE refcur_t IS REF CURSOR 
       refcur refcur_t;
      e_id number;
      e_name varchar2(50);
BEGIN
      OPEN refcur FOR
      SELECT id,name FROM employees;
      FETCH refcur INTO e_id,e_name;
      WHILE refcur%FOUND LOOP
             dbms_output.put_line(‘#’||e_id||’:’||e_name);
             FETCH refcur INTO e_id,e_name;
      END LOOP;
      CLOSE refcur;
END;

根据用户的输入(员工、部门)打印信息

DECLARE
      TYPE refcur_t IS REF CURSOR;
      refcur refcur_t;
      p_id NUMBER;
      p_name VARCHAR2(50);
      selection VARCHAR2(1) :=UPPER(SUBSTR(‘&tab’,1,1));
BEGIN
      IF selection = ‘E’ THEN
             OPEN refcur FOR
                    SELECT id,name FROMemployees;
             dbms_output.put_line(‘===员工信息===’);
      ELSEIF selection = ‘D’ THEN
             OPEN refcur FOR
                    SELECTdepartment_id,department_name FROM departments;
             dbms_output.put_line(‘===部门信息===’);
      ELSE
             dbms_output.put_line(‘请输入员工信息E或部门信息D’);
             RETURN;
      END IF;
      FETCH refcur INTO p_id,p_name;
      WHILE refcur%FOUND LOOP
             dbms_output.put_line(‘#’||p_id||’:’||p_name);
             FETCH refcur INTO p_id,p_name;
      END LOOP;
      CLOSE refcur;
END;

创建动态
SQL
语句。

静态SQL,编译时确定。

动态SQL,不编译,执行时动态确定;根据用户输入参数等才能确定SQL语句;解决PL/SQL中不支持DDL语句的问题。

创建动态DML.DDLSQL语句语法:

EXECUTEIMMEDIATE ‘DMLDDL语句’;[INTO<变量序列>] [USING <参数序列>];只能执行返回一行或0行的语句。

如果后面的语句是个select语句,则可以使用into子句用于接收select语句选择的记录值。可以是一个变量序列,或者一个记录型变量也就是record型的变量。如果SQL语句中有参数需要动态确定,那么我们使用USING子句,USING子句用于绑定输入的参数变量。SQL语句中若有参数,使用”:参数名

示例:动态创建表

BEGIN
      EXECUTE IMMEDIATE
             ‘CREATE TABLE bonus(id NUMBER,amtNUMBER)’;
END;

示例:动态查询一个员工电话

DECLARE
      sql_stmt VARCHAR2(200);
      emp_id NUMBER(10) :=’&emp_id’;
      emp_rec employees%ROWTYPE;
BEGIN
      sql_stmt :=’select * from employees WHEREid =:id’;
      EXECUTE IMMEDIATE sql_stmt INTO emp_recUSING emp_id;
END;

示例
:
动态插入记录

DECLARE
      Sql_stmt varchar2(200);
      emp_id NUMBER(10) := ‘&emp_id’;
      emp_rec employees%ROWTYPE;
BEGIN
      sql_stmt := ‘INSERT INTO employees(id)values(:id)’;
      EXECUTE IMMEDIATE sql_stmt USING emp_id;
      Dbms_output.put_line(emp.rec.phone);
END;

EXECUTEIMMEDIATE
语句只能返回一行或没有返回,如果编写返回多行的
SQL
语句,可以使用
ref
动态游标,他的语法:
OPEN cursor_name FOR <SQL
语句
> [USING <
参数序列
>];

示例:动态输出工资大于某个数额的员工信息

DECLARE
      e_id NUMBER(10);
      e_name VARCHAR2(50);
      s_salary NUMBER(8);
      TYPE c_type is REF CURSOR;
      cur c_type;
      p_salary NUMBER := ‘&p_id’;
BEGIN
      OPEN cur FOR ‘selecte.id,e.name,e.salaryvalue from employees e,salary s where e.id=s.employeeid ands.salaryvalue >:sal ORDER BY id ASC’;
      USING p_salary;
      dbms_output.put_line(‘薪水大于’||p_salary||’的员工有:’);
      LOOP
             FETCH cur INTOe_id,e_name,e_salary;
             EXIT WHEN cur%NOTFOUND;
             dbms_output.put_line(‘编号:’||e_id||’姓名:’||e_name||’薪水:’||e_salary);
END LOOP
      CLOSE cur;
END;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152491.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月23日 上午7:36
下一篇 2022年6月23日 上午7:36


相关推荐

  • 前端模板引擎

    前端模板引擎一 为什么要使用模板引擎关于为什么要使用模板引擎 就我现在的项目而言 我还停留在进行发送 Ajax 请求到后台后 利用模板引擎拼接接受到的 JSON 字符串 展现到页面的地步 按照我老师的一句话表达 不用重复制造轮子 对于为什么要使用模板引擎的解释 我看过最好的回答来自知乎上 niko 的回答 模板最本质的作用是 变静为动 一切利用这方面的都是优势 不利于的都是劣势 要很好地实现 变静为动 的目的 有

    2026年3月18日
    2
  • 23种常用设计模式的UML类图

    23种常用设计模式的UML类图23种常用设计模式的UML类图本文UML类图参考《HeadFirst设计模式》(源码)与《设计模式:可复用面向对象软件的基础》(源码)两书中介绍的设计模式与UML图。整理常用设计模式的类图,一

    2022年6月30日
    31
  • KeyValuePair 和 Dictionary 的关系和区别「建议收藏」

    KeyValuePair 和 Dictionary 的关系和区别「建议收藏」KeyValuePair 和 Dictionary 的关系1、KeyValuePaira、KeyValuePair是一个结构体(struct);b、KeyValu

    2022年7月4日
    29
  • 1. C语言—输出格式大全[通俗易懂]

    1. C语言—输出格式大全[通俗易懂]1.C语言—输出格式大全#include<stdio.h>intmain(){ //1.整形输出 inta=298;//输出十进制用%d printf(“1.十进制: a=%d\n”,a);//只能采用英文双引号格式,不能用单引号 //2.输出八进制用%o printf(“2.八进制:a=%o\n”,a); //3.使用%#o,可以输出八进制数的前导符(在八进制数前面加一个0,用来标识八进制数), printf(“3.前导

    2022年7月24日
    14
  • 【甘道夫】Apache Hadoop 2.5.0-cdh5.2.0 HDFS Quotas 配额控制

    【甘道夫】Apache Hadoop 2.5.0-cdh5.2.0 HDFS Quotas 配额控制

    2021年12月16日
    44
  • Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值

    Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值Vue2.0传值方式:在Vue的框架开发的项目过程中,经常会用到组件来管理不同的功能,有一些公共的组件会被提取出来。这时必然会产生一些疑问和需求?比如一个组件调用另一个组件作为自己的子组件,那么我们如何进行给子组件进行传值呢?如果是电商网站系统的开发,还会涉及到购物车的选项,这时候就会涉及到非父子组件传值的情况。当然你也可以用Vuex状态管理工具来实现,这部分我们后续会单独介绍。先给大家介绍Vue常见的三种传值方式

    2022年5月13日
    40

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号