ORACLE可以用EXECUTE IMMEDIATE来执行动态SQL,但在动态SQL中如果涉及到变量,一定要使用USING方法来绑定变量,不能直接把变量拼接到SQL执行,否则会严重影响执行的性能。

动态SQL不绑定变量,即直接拼接变量到SQL,会导致每次执行的SQL都不一样,每次执行时数据库都要重新解析SQL,一方面解析SQL是要花费一定代价的,减慢了执行的速度,另外一方面解释完的SQL会放在数据库SQL缓存里,大量无用的SQL放在缓存里,容易导致缓存不足,进而影响其他SQL的执行。

下面我们以实际例子来说明不绑定变量对于执行效率的影响。例子中我们会建立一张测试表,然后用3种不同的方法插入相同数量的数据,根据执行的时间来分析效率。

1. 建立一张测试表T_TEST_VAR

CREATE TABLE T_TEST_VAR

(

ID NUMBER(10) NOT NULL,

MESSAGE VARCHAR2(100)

)

2.1 使用正常的插入语句插入

declare

i integer;

begin

for i in 1 .. 100 loop

--直接插入SQL,也是绑定变量,不需要重复解析SQL

insert into T_TEST_VAR (id, message) values (i, 'a');

end loop;

end;

结果用时0.268秒

2.2 使用绑定变量的动态SQL插入

declare

i integer;

V_SQL VARCHAR2(2000);

begin

V_SQL := 'insert into T_TEST_VAR (id, message) values (:1, ''a'')';

for i in 1 .. 100 loop

--动态SQL绑定变量,不需要重复解析SQL

EXECUTE IMMEDIATE V_SQL USING i;

end loop;

end;

结果用时0.224秒

2.3 使用不绑定变量的动态SQL插入

declare

i integer;

V_SQL VARCHAR2(2000);

begin

for i in 1 .. 100 loop

--不绑定变量,每次都要重新解析SQL

V_SQL := 'insert into T_TEST_VAR2 (id, message) values ('||i||', ''a'')' ;

EXECUTE IMMEDIATE V_SQL;

end loop;

end;

结果用时0.719秒

从上面的数据来看,方案3明显会慢很多,但是由于数据量比较小,差距还不是太大。

下面我们再把上面循环的次数由100改成1000和10000进行测试,结果如下:

从10000条比较中,我们就能更明显看到SQL不绑定变量对于执行效率的巨大影响,SQL绑定变量执行只要1秒,而SQL不绑定变量(使用SQL拼接方法)执行则需要52秒。

所以我们平时在写SQL时应该尽量避免使用不绑定变量的动态SQL,特别是动态SQL会大量执行的情况下。