1. 首先看看Oracle的定义:
1) EXECUTE IMMEDIATE 是 PL/SQL 语言中用于动态执行 SQL 语句的关键字。它可以将 SQL 语句作为一个字符串进行封装,并在运行时动态执行该字符串所代表的 SQL 语句。
用法格式如下:
EXECUTE IMMEDIATE <dynamic SQL string> [INTO <variable list>] [USING <bind variable list>];
- \<dynamic SQL string>:需要实际执行的SQL语句字符串;
- \<variable list>:可选,用于指定需要将 SQL 语句返回的结果存入一个或多个变量中;
- \<bind variable list>:可选,绑定变量列表,使 SQL 语句能够动态地接受外部提供的数据。
例如,下面的示例演示了如何使用 EXECUTE IMMEDIATE 动态执行查询语句并将结果存储到变量中:
DECLARE
-- 声明所需变量
v_deptno INTEGER := 10;
v_ename VARCHAR2 (100);
BEGIN
-- 动态拼接 SQL 语句,并执行
EXECUTE IMMEDIATE 'SELECT ename FROM emp WHERE deptno = :1' USING IN v_deptno;
END;
/
2) 使用EXECUTE IMMEDIATE的注意事项
使用 EXECUTE IMMEDIATE 需要注意以下几个方面:
- SQL 注入攻击:使用 EXECUTE IMMEDIATE 执行动态 SQL 语句时,需要注意动态SQL字符串的安全性,以避免 SQL 注入攻击;
- 受到执行环境限制:EXECUTE IMMEDIATE 中的字符串中无法使用变量和 PL/SQL 代码块;
- 显式类型转换:在动态 SQL 中,需要进行显式类型转换,以避免不同类型之间的兼容性问题。
2. LightDB支持情况
LightdbDB从23.4版本开始支持该用法。注意点如下:
1) 执行的sql只支持1层匿名块
2) 暂不支持into...using
3) 支持using in/out用法
4) 暂不支持using 常量
验证用例如下:
drop PROCEDURE TargetProcedure;
CREATE OR REPLACE PROCEDURE TargetProcedure(
p_input1 IN VARCHAR2,
p_input2 IN NUMBER,
p_output1 OUT VARCHAR2,
p_output2 OUT NUMBER
) AS
BEGIN
DBMS_Output.PUT_LINE('TargetProcedure begin-> p_input1 '||' is: '||p_input1);
DBMS_Output.PUT_LINE('TargetProcedure begin-> p_input2 '||' is: '||p_input2);
DBMS_Output.PUT_LINE('TargetProcedure begin-> p_output1 '||' is: '||p_output1);
DBMS_Output.PUT_LINE('TargetProcedure begin-> p_output2 '||' is: '||p_output2);
p_output1 := 'Response from TargetProcedure: ' || p_input1;
p_output2 := p_input2 * 10;
DBMS_Output.PUT_LINE('TargetProcedure end-> p_input1 '||' is: '||p_input1);
DBMS_Output.PUT_LINE('TargetProcedure end-> p_input2 '||' is: '||p_input2);
DBMS_Output.PUT_LINE('TargetProcedure end-> p_output1 '||' is: '||p_output1);
DBMS_Output.PUT_LINE('TargetProcedure end-> p_output2 '||' is: '||p_output2);
END TargetProcedure;
/
drop PROCEDURE MainProcedure;
CREATE OR REPLACE PROCEDURE MainProcedure(
main_input1 IN VARCHAR2,
main_input2 IN NUMBER,
main_output1 OUT VARCHAR2,
main_output2 OUT NUMBER
) AS
BEGIN
main_output2 := 0;
main_output1 := '操作成功';
-- 使用EXECUTE IMMEDIATE来执行动态SQL,并传递参数
DBMS_Output.PUT_LINE('MainProcedure begin-> main_input1 '||' is: '||main_input1);
DBMS_Output.PUT_LINE('MainProcedure begin-> main_input2 '||' is: '||main_input2);
DBMS_Output.PUT_LINE('MainProcedure begin-> main_output1 '||' is: '||main_output1);
DBMS_Output.PUT_LINE('MainProcedure begin-> main_output2 '||' is: '||main_output2);
EXECUTE IMMEDIATE 'BEGIN TargetProcedure(:p_input1, :p_input2, :p_output1, :p_output2); END;'
USING IN main_input1, IN main_input2, OUT main_output1, OUT main_output2;
DBMS_Output.PUT_LINE('MainProcedure end-> main_input1 '||' is: '||main_input1);
DBMS_Output.PUT_LINE('MainProcedure end-> main_input2 '||' is: '||main_input2);
DBMS_Output.PUT_LINE('MainProcedure end-> main_output1 '||' is: '||main_output1);
DBMS_Output.PUT_LINE('MainProcedure end-> main_output2 '||' is: '||main_output2);
END MainProcedure;
/
详细语法可参考LightDB官网查看: