目录

动态SQL

execute immediate语句

带参数使用

作业

动态游标

动态游标类型声明

动态游标使用

强类型游标

作业2

遗忘点复习


动态SQL

plsql里面只能执行 select insert update delete ,想执行create怎么办?其他复杂功能?

使用动态sql,不能加分号,单引号实现转义功能''''

在Oracle数据库开发PL/SQL块中我们使用的SQL分为:静态SQL语句和动态SQL语句。所谓静态SQL指在PL/SQL块中使用的SQL语句在编译时是明确的,执行的是确定对象。而动态SQL是指在PL/SQL块编译时SQL语句是不确定的,如根据用户输入的参数的不同而执行不同的操作。编译程序对动态语句部分不进行处理,只是在程序运行时动态地创建语句、对语句进行语法分析并执行该语句。Oracle中动态SQL可以通过本地动态SQL来执行,也可以通过DBMS_SQL包来执行。本地动态SQL是使用EXECUTE IMMEDIATE语句来实现的。 

execute immediate语句

execute immediate sql语句(字符串,也可以是字符串变量) [into(只有在执行查询时使用)变量,...] [using 参数,...];

--不能执行语句,原有能执行的语句也可以放在里面

declare

v_sql varchar2(1000);

begin

v_sql :=

'create table stest(sno varchar(20),sdate date)';

dbms_output.put_line(v_sql);

execute immediate v_sql;

end;

--增删改查也可以使用动态sql,查询需要使用into

declare

v_sql varchar2(200);

v emp%rowtype;

begin

v_sql := 'select * from emp where empno=7369';

execute immediate v_sql into v;

dbms_output.put_line(v.empno||v.ename);

end;

--带输入且判断的复杂动态sql

declare

v_sql varchar2(200);

v emp%rowtype;

eno varchar(4):='&请输入编号';

begin

v_sql := 'select * from emp ';

if eno is not null then

v_sql:=v_sql||' where empno='||eno;

else

v_sql:=v_sql||' where rownum=1';

end if;

execute immediate v_sql into v;

dbms_output.put_line(v.empno||v.ename);

end;

--输入课程编号,如果不输入则显示所有数据第一条,如果输入显示当前课程的第一条

select * from sc where cno='c002' and rownum=1

select * from sc where rownum=1

declare

dsql varchar2(1000);

sc1 sc%rowtype;

cnoin varchar2(10):='&请输入课程编号';

begin

dsql:='select * from sc where ';

if cnoin is null then

dsql:=dsql||'rownum=1';

else

dsql:=dsql||'cno='''||cnoin||''' and rownum=1';

end if;

dbms_output.put_line(dsql);

execute immediate dsql into sc1;

dbms_output.put_line(sc1.sno||' '||sc1.cno||' '||sc1.score);

end;

带参数使用

declare

-- 声名一个变量保存sql语句

v_sql varchar2(255);

-- 声名一个rowtype类型变量保存一条员工信息

v emp%rowtype;

-- 声名一个变量接收从键盘输入的员工编号

v_empno emp.empno%type:='&empno';

begin

v_sql:='select * from emp where empno=:1';

dbms_output.put_line(v_sql);

execute immediate v_sql into v using v_empno;

-- execute immediate v_sql into v using v_empno;

-- 打印变量v的值

dbms_output.put_line(v.empno||v.ename);

execute immediate v_sql into v using 7839;

-- execute immediate v_sql into v using v_empno;

-- 打印变量v的值

dbms_output.put_line(v.empno||v.ename);

end;

作业

/*1、使用动态sql实现输入员工编号查询员工信息,如果不输入则显示所有员工的第一

条,显示员工姓名和工资*/

declare

dsql varchar2(1000):='select ename,sal from emp where empno=';

dsqldefault varchar2(1000):='select ename,sal from emp where rownum=1';

v_empno varchar2(10):='&输入员工编号';

type names is record(

ename emp.ename%type,

sal emp.sal%type

);

v names;

begin

  if v_empno is not null then

    execute immediate concat(dsql,v_empno) into v;

    else

      execute immediate dsqldefault into v;

      end if;

      dbms_output.put_line(v.ename||'  '||v.sal);  

  end;

/*2、搜索一个员工信息,输入工资和工作岗位,如果输入为空则显示不带条件的第一条;

如果不为空则显示带条件的第一条,显示员工姓名和工资

提示:

1000为测试的输入工资,SALESMAN为测试的输入工作岗位

select * from emp where sal>1000 and job = 'SALESMAN' and rownum=1

select * from emp where sal>1000 and rownum=1

select * from emp where job = 'SALESMAN' and rownum=1

select * from emp where rownum=1*/

declare

dsql varchar2(2000);

type names is record(

ename emp.ename%type,

sal emp.sal%type

);

v names;

v_sal varchar2(10):='&输入工资';

v_job varchar2(20):='&输入工作岗位';

begin

  if v_sal is  not null and v_job is  not null then

    dsql:='select ename,sal from emp where sal=''||v_sal||''and job='||v_job;

    elsif v_sal is not  null and v_job is null then

      dsql:='select ename,sal from emp where sal='||v_sal;

      elsif v_sal is null and v_job is not null then

        dsql:='select ename,sal from emp where job='||v_job;

        else dsql:='select ename,sal from emp where rownum=1';

        end if;

      execute immediate dsql into v;

      dbms_output.put_line(v.ename||'   '||v.sal); 

  end;

  

动态游标

在程序运行过程中,把一个游标变量在不同时刻关联不同的查询语句,也就是使用一个游标变量可以获取多个不同的结果集。通过把动态游标作为参数传递给另一个过程或函数使用,通过这种方式达到共享结果集的目的,把一个游标的内容(结果集)赋值给另外一个游标变量。

动态游标声明步骤:

●声明动态游标类型

●声明动态游标名称

动态游标类型声明

弱类型动态游标系统自带了一个直接使用即可: sys_refcursor

强类型动态游标只能配合静态sql语句使用,无法和动态sql配合使用。

弱类型动态游标能够执行动态sql 以及配合绑定变量。

示例:

refcur_emp sys_refcursor;

动态游标使用

使用 open 打开动态游标并给其绑定结果集

open 动态游标名 for sql语句;

动态游标无法使用for循环打开。 

--没有返回类型的弱类型,一般用sys_refcursor,可以省略步骤,为了返回类型铺垫

declare

cursor cur1 is select * from emp where empno=7499;

emp1 emp%rowtype;

emp2 emp%rowtype;

n1 number(4):=5;

type newcur is ref cursor;--弱类型游标类型

cur2 newcur;--游标变量

begin

open cur2 for select * from emp where empno=7499;

fetch cur2 into emp2;

dbms_output.put_line(emp2.ename);

close cur2;

dbms_output.put_line(n1);

n1:=6;

dbms_output.put_line(n1);

open cur1;

fetch cur1 into emp1;

dbms_output.put_line(emp1.ename);

close cur1;

end;

--弱类型动态游标

declare

emp2 emp%rowtype;

cur2 sys_refcursor;--游标变量

begin

open cur2 for select * from emp where empno=7499;

fetch cur2 into emp2;

dbms_output.put_line(emp2.ename);

close cur2;

end;

--动态游标可以随时换查询结果集

declare

emp2 emp%rowtype;

cur2 sys_refcursor;--游标变量

dept2 dept%rowtype;

begin

open cur2 for select * from emp where empno=7499;

fetch cur2 into emp2;

dbms_output.put_line(emp2.ename);

close cur2;

open cur2 for select * from dept where deptno=20;

fetch cur2 into dept2;

dbms_output.put_line(dept2.dname);

close cur2;

end;

--while循环

declare

emp2 emp%rowtype;

cur2 sys_refcursor;--游标变量

begin

open cur2 for select * from emp;

fetch cur2 into emp2;

while cur2%found

loop

dbms_output.put_line(emp2.ename);

fetch cur2 into emp2;

end loop;

close cur2;

end;

--动态sql弱类型动态游标,输入部门编号,不输入代表所有

declare

dsql varchar2(1000);

dno varchar2(10):='&请输入部门编号';

ename1 varchar2(10);

job1 varchar2(10);

cur1 sys_refcursor;

begin

dsql:='select ename,job from emp ';

if dno is not null then

dsql:=dsql||'where deptno='||dno;

end if;

dbms_output.put_line(dsql);

open cur1 for dsql;

fetch cur1 into ename1,job1;

while cur1%found

loop

dbms_output.put_line(ename1||job1);

fetch cur1 into ename1,job1;

end loop;

close cur1;

end; 

--二重循环动态游标显示

declare

cur1 sys_refcursor;

cur2 sys_refcursor;

dept1 dept%rowtype;

emp1 emp%rowtype;

begin

open cur1 for select * from dept;

fetch cur1 into dept1;

while cur1%found

loop

dbms_output.put_line(dept1.deptno||dept1.dname);

open cur2 for select * from emp where deptno=dept1.deptno;

fetch cur2 into emp1;

while cur2%found

loop

dbms_output.put_line(' '||emp1.deptno||emp1.ename);

fetch cur2 into emp1;

end loop;

close cur2;

fetch cur1 into dept1;

end loop;

close cur1;

end;

强类型游标

declare

type names is record(

ename varchar2(10),

dname varchar2(10)

);

zs names;

type curtype is ref cursor return names;

cur1 curtype;

begin

open cur1 for select dname,ename from emp inner join dept on emp.deptno=dept.deptno;

fetch cur1 into zs;

while cur1%found

loop

dbms_output.put_line(zs.name1||zs.name2);

fetch cur1 into zs;

end loop;

close cur1;

end;

作业2

--1、弱类型动态游标,显示所有员工名称,工作

declare

rlx sys_refcursor;

type names is record(

ename emp.ename%type,

job emp.job%type

);

ej names;

begin

  open rlx for select ename,job from emp;

  fetch rlx into ej;

  while rlx%found

    loop

      dbms_output.put_line(ej.ename||'  '||ej.job);

      fetch rlx into ej;

      end loop;

      close rlx;

  end;

/*2、根据输入的部门编号显示员工编号,工作,若没有输入部门编号则显示所有,使用动

态sql+弱类型动态游标实现*/

declare

dsql varchar2(2000);

rlx sys_refcursor;

v_deptno varchar2(3):='&输入部门编号显示员工编号和工作';

type names is record(

empno emp.empno%type,

job emp.job%type

); 

v_ej names;

begin

  if v_deptno is null then

    dsql:='select empno,job from emp';

    open rlx for dsql;

    fetch rlx into v_ej;

    while rlx%found

      loop

        dbms_output.put_line(v_ej.empno||'   '||v_ej.job);

        fetch rlx into v_ej;

        end loop;

        close rlx;

    else 

      dsql:='select empno,job from emp where deptno='||v_deptno;

      open rlx for dsql;

      fetch rlx into v_ej;

      while rlx%found

        loop

           dbms_output.put_line(v_ej.empno||'   '||v_ej.job);

           fetch rlx into v_ej;

          end loop;

         close rlx;

      end if;

  end;

/*3、根据输入显示学员姓名、课程编号及课程成绩,输入学号不输入课程号直接显示学员

姓名和所有课程编号和成绩,输入学号和课程号显示对应课程成绩,使用动态sql+弱类

型动态游标实现*/

declare

type names is record(

cno sc.cno%type,

score sc.score%type

);

sc2 names;

v_name student.sname%type;

v_score sc.score%type;

dsql varchar2(2000);

rlx sys_refcursor;

v_sno sc.sno%type:='&输入学号';

v_cno sc.cno%type:='&输入课程号';

begin

  if v_sno is not null and v_cno is null then

    select sname into v_name from student where sno=v_sno;

    dsql:='select cno,score from sc where sno='''||v_sno||'''';

    dbms_output.put_line(v_name);

    open rlx for dsql;

    fetch rlx into sc2;

    while rlx%found

      loop

        dbms_output.put_line(sc2.cno||'    '||sc2.score);

        fetch rlx into sc2;

        end loop;

    close rlx; 

    elsif v_sno is not null and v_cno is not null then

      select score into v_score from sc where sno=v_sno and cno=v_cno;

      dbms_output.put_line(v_score); 

    end if; 

  end;

--4、通过teacher表显示各个课程信息,二重循环弱类型游标,同上机练习7.2的效果图

declare

rlx sys_refcursor;

rlx2 sys_refcursor;

v_teacher teacher%rowtype;

v_course course%rowtype;

begin

  open rlx for select * from teacher;

  fetch rlx into v_teacher;

  while rlx%found

    loop

    dbms_output.put_line(v_teacher.tno||'---'||v_teacher.tname);

    fetch rlx into v_teacher;

    open rlx2 for select * from course where tno=v_teacher.tno;

    fetch rlx2 into v_course;

    while rlx2%found

      loop

        dbms_output.put_line('     '||v_course.cno||'-----'||v_course.cname||'-----'||v_course.tno); 

        fetch rlx2 into v_course;

        end loop;

    close rlx2;

    end loop;

  close rlx;

  end;

--5、使用强类型游标显示教师姓名及所教课程名称

declare

type names is record(

tname teacher.tname%type,

cname course.cname%type

);

t names;

type cur is ref cursor return names;

A cur;

begin

  open A for select tname,cname

  from teacher left join course on teacher.tno=course.tno;

  fetch A into t;

  while A%found

    loop

    dbms_output.put_line(t.tname||'-----'||t.cname); 

    fetch A into t;

    end loop;

  close A;

end;

遗忘点复习

number类型不能为空。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部