Oracle中的动态SQL

  内容摘要: PL/SQL 开发过 程中,使用 SQL PL/SQL 可以 实现 大部份的需求,但是在某些特殊的情况下,在 PL/SQL 中使用 准的 SQL 句或 DML 句不能 实现 自己的需求,比如需要 动态 建表或某个不确定的操作需要 动态执 行。 就需要使用 动态 SQL 实现 。本文通 几个 例来 详细 动态 SQL 的使用。  

  本文适宜者范 Oracle ,中

  系统环境:

   OS windows  2000 Professional ( 英文版 )

    Oracle 8.1.7.1.0

  正文:

   一般的 PL/SQL 程序 设计 中,在 DML 和事 控制的 句中可以直接使用 SQL ,但是 DDL 句及系 控制 句却不能在 PL/SQL 中直接使用,要想 实现 PL/SQL 中使用 DDL 句及系 控制 句,可以通 使用 动态 SQL 实现

  首先我 们应该 了解什 动态 SQL ,在 Oracle 数据 库开发 PL/SQL 中我 使用的 SQL :静 SQL 句和 动态 SQL 句。所 SQL 指在 PL/SQL 中使用的 SQL 句在 编译时 是明确的, 行的是确定 象。而 动态 SQL 是指在 PL/SQL 块编译时 SQL 句是不确定的,如根据用 户输 入的参数的不同而 行不同的操作。 编译 程序 对动态语 句部分不 理,只是在程序运行 时动态 句、 对语 法分析并 该语 句。

   Oracle 动态 SQL 可以通 本地 动态 SQL 行,也可以通 DBMS_SQL 包来 行。下面就 情况分 别进 明:

  一、本地动态SQL

  本地 动态 SQL 是使用 EXECUTE IMMEDIATE 句来 实现 的。

  1、本地动态SQLDDL句:

  需求:根据用 户输 入的表名及字段名等参数 动态 建表。

create  or replace procedure proc_test
(
table_name in varchar2, --表名
field1 in varchar2, --字段名
datatype1 in varchar2, --字段
field2 in varchar2, --字段名
datatype2 in varchar2 --字段
as 
str_sql varchar2(500);
begin
 
str_sql:=’create table ’||table_name||’(’||field1||’ ’||datatype1||’,’||field2||’ ’||datatype2||’)’;
execute
 immediate str_sql; -- 动态执 DDL
exception
 
when
 others then 
null
;
end
 ;
  以上是 编译 的存 储过 程代 。下面 行存 储过 动态 建表。

SQL execute proc_test(’dinya_test’,’id’,’number(8) not null’,’name’,’varchar2(100)’);

PL/SQL procedure successfully completed

SQL
desc dinya_test;
Name
 Type Nullable Default Comments 
---- ------------- -------- ------- -------- 
ID
 NUMBER(8)

NAME
 VARCHAR2(100) Y

SQL
>
  到 里,就 实现 了我 的需求,使用本地 动态 SQL 根据用 户输 入的表名及字段名、字段 型等参数来 实现动态执 DDL 句。

  2、本地动态SQLDML句。

  需求:将用 户输 入的 插入到上例中建好的 dinya_test 表中。

create  or replace procedure proc_insert
(
id
 in number, -- 入序号
name
 in varchar2 -- 入姓名
as 
str_sql varchar2(500);
begin
 
str_sql:=’insert into dinya_test values(:1,:2)’;
execute
 immediate str_sql using id,name; -- 动态执 行插入操作
exception
 
when
 others then 
null
;
end
 ;
   行存 储过 程,插入数据到 测试 表中。

SQL execute proc_insert(1,’dinya’);
PL/SQL procedure successfully completed
SQL
select * from dinya_test;
ID
 NAME
1 dinya
  在上例中,本地 动态 SQL DML 使用了 using 子句,按 序将 入的 值绑 定到 量,如果需要 出参数,可以在 动态 SQL 候,使用 RETURNING INTO  子句,如:

declare
p_id number:=1;
v_count number;
begin
 
v_string:=’select count(*) from table_name a where a.id=:id’;
execute
 immediate v_string into v_count using p_id; 
end
 ;
  更多的 动态 SQL 于返回 为输 行参数模式的 问题 请读 者自行做 测试

  二、使用DBMS_SQL

  使用 DBMS_SQL 实现动态 SQL 步骤 如下: A 、先将要 行的 SQL 句或一个 放到一个字符串 量中。 B 、使用 DBMS_SQL 包的 parse 程来分析 字符串。 C 、使用 DBMS_SQL 包的 bind_variable 程来 量。 D 、使用 DBMS_SQL 包的 execute 函数来 句。

  1、使用DBMS_SQLDDL

  需求:使用 DBMS_SQL 包根据用 户输 入的表名、字段名及字段 型建表。

create  or replace procedure proc_dbms_sql
(
table_name in varchar2, --表名
field_name1 in varchar2, --字段名
datatype1 in varchar2, --字段
field_name2 in varchar2, --字段名
datatype2 in varchar2 --字段
)as
v_cursor number; --
v_string varchar2(200); -- 字符串
v_row number; --行数
begin
v_cursor:=dbms_sql.open_cursor; -- 为处 理打
v_string:=’create table ’||table_name||’(’||field_name1||’ ’||datatype1||’,’||field_name2||’ ’||datatype2||’)’;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); --分析
v_row:=dbms_sql.execute(v_cursor); --
dbms_sql.close_cursor(v_cursor); -- 关闭
exception
when
 others then
dbms_sql.close_cursor(v_cursor); -- 关闭
raise
;
end
;
  以上 编译 后, 建表 构:

SQL execute proc_dbms_sql(’dinya_test2’,’id’,’number(8) not null’,’name’,’varchar2(100)’);

PL/SQL procedure successfully completed

SQL
desc dinya_test2;
Name
 Type Nullable Default Comments 
---- ------------- -------- ------- -------- 
ID
 NUMBER(8) 
NAME
 VARCHAR2(100) Y 

SQL
>
  2、使用DBMS_SQLDML

  需求:使用 DBMS_SQL 包根据用 户输 入的 更新表中相 对应 记录

   看表中已有 记录

SQL select * from dinya_test2;
ID
 NAME
1 Oracle
2 CSDN
3 ERP
SQL
>
  建存 储过 程,并 编译

create  or replace procedure proc_dbms_sql_update
(
id
 number,
name
 varchar2
)as
v_cursor number; --
v_string varchar2(200); --字符串
v_row number; --行数
begin
v_cursor:=dbms_sql.open_cursor; -- 为处 理打
v_string:=’update dinya_test2 a set a.name=:p_name where a.id=:p_id’;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); --分析
dbms_sql.bind_variable(v_cursor,’:p_name’,name); --
dbms_sql.bind_variable(v_cursor,’:p_id’,id); --
v_row:=dbms_sql.execute(v_cursor);           -- 动态 SQL
dbms_sql.close_cursor(v_cursor); -- 关闭
exception
when
 others then
dbms_sql.close_cursor(v_cursor); -- 关闭
raise
;
end
;
   程,根据用 户输 入的参数更新表中的数据:

SQL execute proc_dbms_sql_update(2,’csdn_dinya’);

PL/SQL procedure successfully completed

SQL
select * from dinya_test2;
ID
 NAME
1 Oracle
2 csdn_dinya
3 ERP
SQL
>
   程后将第二条的 name 字段的数据更新 csdn_dinya 这样 就完成了使用 dbms_sql 包来 DML 句的功能。

  使用 DBMS_SQL 中,如果要 行的 动态语 句不是 查询语 句,使用 DBMS_SQL.Execute DBMS_SQL.Variable_Value 行,如果要 动态语 句是 查询语 句, 要使用 DBMS_SQL.define_column 义输 量,然后使用 DBMS_SQL.Execute , DBMS_SQL.Fetch_Rows, DBMS_SQL.Column_Value DBMS_SQL.Variable_Value 查询 并得到 果。

  总结说明:

  在 Oracle 开发过 程中,我 可以使用 动态 SQL DDL 句、 DML 句、事 控制 句及系 控制 句。但是需要注意的是, PL/SQL 中使用 动态 SQL DDL 句的 候与 的不同,在 DDL 中使用 量是非法的( bind_variable (v_cursor,’:p_name’,name) ),分析后不需要 DBMS_SQL.Bind_Variable ,直接将 入的 量加到字符串中即可。另外, DDL 是在 DBMS_SQL.PARSE 时执 行的,所以 DBMS_SQL.EXECUTE 也可以不用,即在上例中的 v_row :=dbms_sql.execute(v_cursor) 部分可以不要。

你可能感兴趣的:(Oracle中的动态SQL)