Oracle基础 动态SQL语句

简介: 原文:Oracle基础 动态SQL语句一、静态SQL和动态SQL的概念。   1、静态SQL   静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了。因为静态SQL是在编写程序时就确定了,我们只能使用SQL中的DML和事务控制语句,但是DDL语句,以及会话控制语句却不能再PL/SQL中直接使用,如动态创建表或者某个不确定的操作时,这就需要动态SQL来实现。
原文: Oracle基础 动态SQL语句

一、静态SQL和动态SQL的概念。

  1、静态SQL

  静态SQL是我们常用的使用SQL语句的方式,就是编写PL/SQL时,SQL语句已经编写好了。因为静态SQL是在编写程序时就确定了,我们只能使用SQL中的DML和事务控制语句,但是DDL语句,以及会话控制语句却不能再PL/SQL中直接使用,如动态创建表或者某个不确定的操作时,这就需要动态SQL来实现。

  2、动态SQL

  动态SQL是指在PL/SQL编译时SQL语句是不确定的,如根据用户输入的参数的不同来执行不同的操作。编译程序对动态语句部分不进行处理,只是在程序运行时动态创建语句,对语句进行分析,病执行该语句。

  静态SQL的优势是性能较高,但不灵活。动态SQL的优势是灵活,缺点是性能稍差。

 

二、动态创建DML、DDL的SQL语句。

  动态创建SQL有一下几类:

  1、DDL语句、DCL语句、非查询的DML语句、单行查询的SELECT语句,这类可以使用EXECUTE IMMEDIATE语句执行。

  2、多行查询的SELECT语句可以使用游标来实现。

  3、通过DBMS_SQL程序包实现。

  下面来介绍以上3种情况:

 

  1、使用EXECUTE IMMEDIATE语句处理相关语句:

  语法:

  EXECUTE IMMEDIATE dynamic_sql_string

  [into define_variable_list]

  [using bind_argument_list];

  例:  

动态创建表t1
--处理DDL、DCL语句,根据用户输入的表明及字段名动态创建表t1
DECLARE
  tablename VARCHAR2(20);        --表名
    field1 VARCHAR2(20);           --字段1名称
    datatype1 VARCHAR2(20);        --字段1类型
    field2 VARCHAR2(20);           --字段2名称
    datatype2 VARCHAR2(20);        --字段2类型
    str_sql VARCHAR2(500);         --拼接SQL语句的字符串
BEGIN
    tablename := 't1';
    field1:='id';
    datatype1:='number';
    field2:='name';
    datatype2:='varchar(20)';
    str_sql := 'create table '||tablename||'('||field1 ||' '||datatype1||','||field2 ||' '||datatype2||')';
    EXECUTE IMMEDIATE str_sql;
    EXCEPTION
        WHEN OTHERS THEN
            DBMS_OUTPUT.put_line('操作失败!');
END;

 

  动态插入数据;  

--动态处理费查询的DML语句:向刚才创建的表中插入数据
DECLARE
  v_id NUMBER;                    --输入序号;
  v_name VARCHAR(20);             --输入姓名;
  str_sql VARCHAR2(500);          --保存拼接的SQL语句
BEGIN
    v_id := &vid;
    v_name := '&name';
    str_sql := 'insert into t1 values(:1,:2)';      --使用占位符代表变量
    EXECUTE IMMEDIATE str_sql
    USING v_id,v_name;                              --使用变量替换SQL中的占位符,v_id替换:1,v_name替换:2,依此类推。
    COMMIT;                                         --执行完毕后直接提交
END;

 

  查询表中的数据有多少行

--处理单行查询的SELECT举例,查询表中的数据有多少行
DECLARE
    v_count NUMBER;
    str_sql VARCHAR2(500);
BEGIN
    str_sql := 'select count(*) from t1';
    EXECUTE IMMEDIATE str_sql INTO v_count;   --将查询的结果存放到变量v_count中。
    DBMS_OUTPUT.put_line(v_count);
END;

 

  绑定变量的优缺点:

  1)可以再库缓存中共享游标,节省了CPU等资源,可以避免额外开销。

  2)SQL语句使用绑定变量可以避免被注入攻击。

  3)绑定变量是一种减少应用程序在分析查询时使用栓锁数目的可靠方法。

  

  不适合使用变量绑定的情况:

  1)对于隔相当长一段时间才执行一次的SQL语句,利用绑定变量的好处hi被不能有效利用而抵消。

  2)在数据仓库的情况下。

  3)在对建有索引的字段,且字段非常大时,利用绑定变量可能会导致查询计划错误,从而导致查询效率非常低。

 

  实现DDL语句中的注意事项:

  PL/SQL块使用动态SQL执行DDL语句的时候与其它不同,在DDL中不能使用绑定变量。

 

  实现DML语句中的注意事项:

  不能使用绑定变量替换实际的数据库对象名(表,视图,列等),只能替换字面两,如果对象名在运行时生成的,我们只能使用字符串拼接。

 

 

  2、通过游标实现多行查询的SELECT语句

  REF游标可以处理返回届国际的动态SQL。实现动态SQL的REF游标声明和普通REF游标相同,知识OPEN时绑定的是动态SQL字符串。

  例:查询emp表中所有的数据。

DECLARE
  TYPE ref_cur IS REF CURSOR;
    rc ref_cur;
    emprow emp%ROWTYPE;
    v_sql VARCHAR2(100):= 'select * from emp where deptno = :x';   --动态执行的SQL语句
BEGIN
    OPEN rc FOR v_sql USING 30;   --打开游标,绑定执行的SQL语句,并传递参数
  LOOP
        FETCH rc INTO emprow;
        EXIT WHEN rc%NOTFOUND;
        dbms_output.put_line('name:'||emprow.ename||'  sal:'||emprow.sal);
    END LOOP;
    CLOSE rc;
END;

 

  3、DBMS_SQL程序包

  DBMS_SQL程序包是系统提供给我们的另一种使用动态SQL的方法。程序包中封装了一些列存储过程,帮助我们动态执行SQL。

  使用DBMS_SQL包实现动态SQL的步骤如下:

  1)将要执行的SQL语句或一个语句块放到一个字符串变量中。

  2)使用DBMS_SQL包的parse过程来分析该字符串。

  3)使用DBMS_SQL包的bind_variable过程来绑定变量。

  4)使用DBMS_SQL包的execute函数来执行语句。

  例:使用DBMS_SQL创建表  

DECLARE
  tablename VARCHAR2(20) :='t2';                 --表名
  field1 VARCHAR2(20) :='id';                    --字段1名称
  datatype1 VARCHAR2(20) :='number';             --字段1类型
  field2 VARCHAR2(20) :='name';                  --字段2名称
  datatype2 VARCHAR2(20) :='varchar(20)';        --字段2类型
  v_sql VARCHAR2(500) := 'create table '||tablename||'('||field1 ||' '||datatype1||','||field2 ||' '||datatype2||')';           --拼接SQL语句的字符串
  v_cursor NUMBER;                                --定义光标
  v_row NUMBER;                                   --行数
BEGIN
    v_cursor:=dbms_sql.open_cursor;                              --为处理打开光标
    dbms_sql.parse(v_cursor,v_sql,dbms_sql.native);              --分析语句;
    v_row:=DBMS_SQL.execute(v_cursor);                           --执行sql语句;
    dbms_sql.close_cursor(v_cursor);                             --关闭光标;
    DBMS_OUTPUT.put_line(v_row);    
END;

  向表中插入一条数据:

DECLARE
  v_id NUMBER := &vid;
    v_name VARCHAR2(20) := '&vname';
    v_sql VARCHAR2(100) := 'insert into t2 values(:id,:name)';
    v_cursor NUMBER;
    v_row NUMBER;
BEGIN
    v_cursor:=dbms_sql.open_cursor;
    dbms_sql.parse(v_cursor,v_sql,dbms_sql.native);
    dbms_sql.bind_variable(v_cursor,':id',v_id);
    dbms_sql.bind_variable(v_cursor,':name',v_name);
    v_row := dbms_sql.execute(v_cursor);
    dbms_sql.close_cursor(v_cursor);
    COMMIT;
    DBMS_OUTPUT.put_line(v_row);
END;

 

  查询EMP中的数据

  

DECLARE
  V_DEPTNO NUMBER := &DEPTNO;
  V_SQL    VARCHAR2(100) := 'select empno,ename,sal from emp where deptno = :deptno';
  V_CURSOR NUMBER;
  V_NO     NUMBER;
  V_ENAME  VARCHAR2(20);
  V_SAL    NUMBER;
    v_start  NUMBER;
BEGIN
  V_CURSOR := DBMS_SQL.OPEN_CURSOR;                                  --打开游标
  DBMS_SQL.PARSE(V_CURSOR, V_SQL, DBMS_SQL.NATIVE);                  --解析动态SQL语句
  DBMS_SQL.BIND_VARIABLE(V_CURSOR, ':deptno', V_DEPTNO);             --传递参数

  DBMS_SQL.DEFINE_COLUMN(V_CURSOR, 1, V_NO);                         --定义输出的列,和查询的列相匹配
  DBMS_SQL.DEFINE_COLUMN(V_CURSOR, 2, V_ENAME,20);
  DBMS_SQL.DEFINE_COLUMN(V_CURSOR, 3, V_SAL);

  v_start := DBMS_SQL.execute(V_CURSOR);                             --执行SQL语句,需要有接受返回值

  LOOP
    EXIT WHEN DBMS_SQL.FETCH_ROWS(V_CURSOR) <= 0;                    --解析游标,
    DBMS_SQL.COLUMN_VALUE(V_CURSOR, 1, V_NO);                         --将当前行的数据写入上面对应的列中。
    DBMS_SQL.COLUMN_VALUE(V_CURSOR, 2, V_ENAME);
    DBMS_SQL.COLUMN_VALUE(V_CURSOR, 1, V_SAL);
  
    DBMS_OUTPUT.PUT_LINE('no:' || V_NO || '  enmae:' || V_ENAME ||'    sal:' || V_SAL);   --输出内容
  END LOOP;
  dbms_sql.close_cursor(v_cursor);                                     --关闭游标
END;

 

目录
相关文章
|
17天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL隐式游标:数据的“自动导游”与“轻松之旅”
【4月更文挑战第19天】Oracle PL/SQL中的隐式游标是自动管理的数据导航工具,简化编程工作,尤其适用于简单查询和DML操作。它自动处理数据访问,提供高效、简洁的代码,但不适用于复杂场景。显式游标在需要精细控制时更有优势。了解并适时使用隐式游标,能提升数据处理效率,让开发更加轻松。
|
17天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标自定义异常:数据探险家的“专属警示灯”
【4月更文挑战第19天】Oracle PL/SQL中的游标自定义异常是处理数据异常的有效工具,犹如数据探险家的警示灯。通过声明异常名(如`LOW_SALARY_EXCEPTION`)并在满足特定条件(如薪资低于阈值)时使用`RAISE`抛出异常,能灵活应对复杂业务规则。示例代码展示了如何在游标操作中定义和捕获自定义异常,提升代码可读性和维护性,确保在面对数据挑战时能及时响应。掌握自定义异常,让数据管理更从容。
|
17天前
|
SQL Oracle 安全
Oracle的PL/SQL游标异常处理:从“惊涛骇浪”到“风平浪静”
【4月更文挑战第19天】Oracle PL/SQL游标异常处理确保了在数据操作中遇到的问题得以优雅解决,如`NO_DATA_FOUND`或`TOO_MANY_ROWS`等异常。通过使用`EXCEPTION`块捕获并处理这些异常,开发者可以防止程序因游标问题而崩溃。例如,当查询无结果时,可以显示定制的错误信息而不是让程序终止。掌握游标异常处理是成为娴熟的Oracle数据管理员的关键,能保证在复杂的数据环境中稳健运行。
|
17天前
|
SQL Oracle 安全
Oracle的PL/SQL异常处理方法:守护数据之旅的“魔法盾”
【4月更文挑战第19天】Oracle PL/SQL的异常处理机制是保障数据安全的关键。通过预定义异常(如`NO_DATA_FOUND`)和自定义异常,开发者能优雅地管理错误。异常在子程序中抛出后会向上传播,直到被捕获,提供了一种集中处理错误的方式。理解和善用异常处理,如同手持“魔法盾”,确保程序在面对如除数为零、违反约束等挑战时,能有效保护数据的完整性和程序的稳定性。
|
17天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL中FOR语句循环游标的奇幻之旅
【4月更文挑战第19天】在Oracle PL/SQL中,FOR语句与游标结合,提供了一种简化数据遍历的高效方法。传统游标处理涉及多个步骤,而FOR循环游标自动处理细节,使代码更简洁、易读。通过示例展示了如何使用FOR循环游标遍历员工表并打印姓名和薪资,对比传统方式,FOR语句不仅简化代码,还因内部优化提升了执行效率。推荐开发者利用这一功能提高工作效率。
|
17天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
17天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL显式游标:数据的“私人导游”与“定制之旅”
【4月更文挑战第19天】Oracle PL/SQL中的显式游标提供灵活精确的数据访问,与隐式游标不同,需手动定义、打开、获取和关闭。通过DECLARE定义游标及SQL查询,OPEN启动查询,FETCH逐行获取数据,CLOSE释放资源。显式游标适用于复杂数据处理,但应注意SQL效率、游标管理及异常处理。它是数据海洋的私人导游,助力实现业务逻辑和数据探险。
|
17天前
|
SQL 存储 Oracle
Oracle的PL/SQL游标:数据的“探秘之旅”与“寻宝图”
【4月更文挑战第19天】Oracle PL/SQL游标是数据探索的关键工具,用于逐行访问结果集。它的工作原理包括定义、打开、FETCH和关闭,允许灵活处理数据。游标有隐式和显式两种类型,适用于不同场景,且支持参数化以增强灵活性。尽管游标在数据处理中不可或缺,但过度使用可能影响性能,因此需谨慎优化。掌握游标技巧,能有效实现业务逻辑,开启数据世界的探秘之旅。
|
17天前
|
SQL Oracle 安全
Oracle的PL/SQL循环语句:数据的“旋转木马”与“无限之旅”
【4月更文挑战第19天】Oracle PL/SQL中的循环语句(LOOP、EXIT WHEN、FOR、WHILE)是处理数据的关键工具,用于批量操作、报表生成和复杂业务逻辑。LOOP提供无限循环,可通过EXIT WHEN设定退出条件;FOR循环适用于固定次数迭代,WHILE循环基于条件判断执行。有效使用循环能提高效率,但需注意避免无限循环和优化大数据处理性能。掌握循环语句,将使数据处理更加高效和便捷。
|
SQL Oracle 关系型数据库
Oracle SQL优化之多表连接
Oracle SQL优化之多表连接
438 0
Oracle SQL优化之多表连接

推荐镜像

更多