静态SQL是前置编译绑定,动态SQL是后期执行时才编译绑定。
场景:
动态SQL适用于表名及查询字段名未知的情况。在已知查询字段名及表名的情况下,使用动态SQL(字符串拼接方式)会增加硬解析的开销,在这种情况下,建议使用静态SQL,这样可以提高执行效率。在过程过程用拼凑的动态sql效率并不高。
因此,真实业务下适用动态sql的场景非常少,使用时也必须注意表结构的变动等因素,应该尽量在业务开发中使用动态sql。本人一般使用动态sql做数据采集;
用execute immediate实现动态sql:
----ddl begin execute immediate \'create table l_test(name varchar2(8))\'; end;
带参数:
declare ----带参数 v_name l_test.name%type; v_insql varchar(100); begin v_name := \'张三\'; v_insql := \'insert into l_test(name)values(:1)\'; execute immediate v_insql using v_name; commit; end;
返回一行记录:
declare ----带参数 v_name l_test.name%type; v_sql varchar(100); v_rec l_test%rowtype; begin v_name := \'张三\'; v_sql := \'select * from l_test t where t.name=:v_n\'; execute immediate v_sql into v_rec using v_name; dbms_output.put_line(v_rec.name); end;
返回多行记录:
declare --v_name l_test.name%type; v_sql varchar(100); type t_rec IS TABLE OF l_test%ROWTYPE; v_arry_test t_rec; begin v_name := \'张三\'; v_sql := \'select * from l_test t\'; execute immediate v_sql bulk collect into v_arry_test; for i in 1 .. v_arry_test.count loop dbms_output.put_line(v_arry_test(i).name); end loop; end;
结合游标:
declare v_name l_test.name%type; v_sql varchar(100); type cur_type is ref cursor; v_cur cur_type; type t_rec IS TABLE OF l_test%ROWTYPE; v_arry_test t_rec; begin v_name := \'张三\'; v_sql := \'select * from l_test t where name=:v_n\'; open v_cur for \'\' || v_sql using v_name; fetch v_cur bulk collect into v_arry_test; close v_cur; for i in 1 .. v_arry_test.count loop dbms_output.put_line(v_arry_test(i).name); end loop; end;