36.动态SQL

本文详细介绍了PLSQL中动态SQL的使用方法,包括动态创建表并返回行数、使用占位符、接收DML更新字段等功能,并展示了如何在游标操作中应用动态SQL。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、引言

       前面介绍的所有内容,所操作的数据库表必须存在,否则执行子程序时就会出现问题,这种方法叫做静态SQLPLSQL中有一种能够定义程序时不指定具体的操作对象,在执行时动态传入对象的技术,叫做动态SQL

二、动态的创建表格并返回表格行数

       下面的代码,我们定义了一个名叫get_table_count_fun的function,该函数接收一个字符串格式的表名作为参数,首先在user_tables中检查存不存在该表,若不存在就创建表,然后获取表中数据行的个数。
    
create or replace function get_table_count_fun(p_table_name varchar2) return number
as
 v_sql varchar2(200);
 v_count number;
begin
 select count(*) into v_count from user_tables where table_name=upper(p_table_name);
 if v_count=0 then
   v_sql:='create table '||p_table_name||'(empno number,ename varchar2(20) )';
   execute immediate v_sql;
 end if;
 v_sql:='select count(*) from '||p_table_Name;
 execute immediate v_sql into v_count;
 return v_count;
end;
/
        可以看到,我们创建表和查询表的方式都是通过动态sql的方式进行的,v_sql是我们创建表和查询表的sql语句,而execute immediate 后面加v_sql就是执行动态sql的方式,如果是DDL语句或者DML语句,直接执行即可;如果是select语句,需要将插叙结果into给你个变量。定义完成上述函数,我们可以在在plsql代码块中执行调用:
declare
 v_count number;
begin
  v_count:=get_table_count_fun('myemp');
  dbms_output.put_line(v_count);
end;
/

三、设置占位符

        使用PLSQL时,可以在sql语句中设置占位符,设置的方式是使用“:占位符名称”,如下面的例子,我们在数据表myemp中插入一条数据:
declare
  v_empno myemp.empno%type :=1;
  v_ename myemp.ename%type :='hyman';
  v_sql varchar2(100);
begin
  v_sql:='insert into myemp values(:eno,:enm)';
  execute immediate v_sql using v_empno,v_ename;
end;
/
       在为占位符指定数据时,我们只需要在execute immediate语句中使用using关键字添加变量列表即可,执行结果如下:

四、接收DML更新的字段

        动态sql中可以使用returning into来获取DML语句影响的数据字段,如下面的代码,我们修改myemp表中empno为1的姓名,然后获取修改后的姓名并打印。
declare
 v_sql varchar2(100);
 v_name myemp.ename%type;
 v_no myemp.empno%type;
begin
 v_no:=1;
 v_sql:='update myemp set ename=''Liuzhihui'' where empno=:eno returning ename into :enm';
 execute immediate v_sql using v_no returning into v_name;
 dbms_output.put_line(v_name);
end;
/
        可以看出,再使用returning into时需要分别在sql语句和execute immediate中使用,在sql语句中指定需要接受的字段以及变量的占位符,在execute immediate中指定接受的变量,需要特别注意的是在sql语句中的表示字符串时单引号需要用两个单引号表示。
        结果如下:

五、批量接收更新的字段

        在前面的文章中我们使用bulk collection into接收过select的多行数据,在动态sql中,我们也可以使用bulk collection into 接收多行更新的字段,我们先在myemp表中再插入一条数据,之后表中的数据如下:

        我们要实现的效果是,删除表中所有的数据,但是要使用索引表批量接收ename并打印出来:
declare
  type ename_index is table of myemp.ename%type index by pls_integer;
  v_ename ename_index;
  v_sql varchar2(100);
begin
  v_sql:='delete from myemp returning ename into :ena';
  execute immediate v_sql returning bulk collect into v_ename;
  for x in 1..v_ename.count loop
    dbms_output.put_line(v_ename(x));
  end loop;
end;
/
        我们发现同接收单个更新的字段相比,批量接收的唯一区别在于execute immediate子句中需要使用bulk collect into,且接收的对象应该是索引表或者数组。这是批量接收删除的字段,更新和插入类似。接下来我们再来看一个批量接收查询字段的例子。
       首先我们需要再次插入刚才删除的数据,然后使用动态sql进行查询操作并接收查询到的人员的ename:
declare
  type ename_varray is varray(100) of myemp.ename%type;
  v_ename ename_varray;
  v_sql varchar2(100);
begin
  v_sql:='select ename from myemp';
  execute immediate v_sql bulk collect into v_ename;
  for x in 1 .. v_ename.count loop
    dbms_output.put_line(v_ename(x));
  end loop;
end;
/
        从上面的代码可以看出,使用动态sql进行select并接收查询结果时,不再需要returning关键字,因为查询操作本身就会返回一个结果集,而不用使用returning显式的去返回一个结果集。
       上面两段代码的执行结果如下:

六、游标操作中使用动态SQL

        
        游标操作中同样可以使用动态SQL,如下面的代码,我们利用动态SQL的游标操作查询empno为1的雇员信息并打印出来:
declare
  cur_emp sys_refcursor;
  v_emprow myemp%rowtype;
  v_empno myemp.empno%type:=1;
begin
  open cur_emp for 'select * from myemp where empno = :eno' using v_empno;
  loop
     fetch cur_emp into v_emprow;
     exit when cur_emp%notfound;
     dbms_output.put_line(v_emprow.empno||' '||v_emprow.ename);
  end loop;
  close cur_emp;
end;
/
        如果需要批量接收数据,还是利用bulk collect into:
declare
  type emp_table is table of myemp%rowtype index by pls_integer;
  cur_emp sys_refcursor;
  v_emps emp_table;
begin
  open cur_emp for 'select * from myemp';
  fetch cur_emp bulk collect into v_emps;
  close cur_emp;
  for x in 1..v_emps.count loop
    dbms_output.put_line(v_emps(x).empno||' '||v_emps(x).ename);
  end loop;
end;
/

























评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值