【问题标题】:How to use dynamic sql in pl/sql?如何在pl/sql中使用动态sql?
【发布时间】:2021-06-25 06:54:29
【问题描述】:
我有以下 pl/sql 过程作为示例(我的过程要大得多,但我的问题是关于动态 sql)。我的问题是如何在 SQL_STMT 中使用变量 V_DATE:
CREATE OR REPLACE PROCEDURE TEST (DATE_A IN DATE) IS
V_DATE DATE;
SQL_STMT VARCHAR2(4000);
BEGIN
V_DATE = DATE_A;
SQL_STMT = 'CREATE TABLE TABLE_1 AS
SELECT *
FROM TABLE_2 A
WHERE A.DATE_FROM = V_DATE';
EXECUTE IMMEDIATE SQL_STMT;
COMMIT;
END TEST;
/
【问题讨论】:
标签:
sql
oracle
plsql
dynamic-sql
【解决方案1】:
您需要连接该值。 (通常绑定变量是个好主意,但它们不能与 DDL 一起使用。)
create or replace procedure test
( date_a in date )
as
sql_stmt varchar2(4000);
begin
sql_stmt :=
'create table table_1 as select * from table_2 a '||
'where a.date_from = date '''||to_char(date_a,'YYYY-MM-DD')||'''';
dbms_output.put_line(sql_stmt);
execute immediate sql_stmt;
end test;
生成的语句将类似于:
create table table_1 as select * from table_2 a where a.date_from = date '2021-03-27'
请注意,这只会工作一次,因为之后表已经存在,所以create table 语句将失败,但这只是一个演示语法的示例。
【解决方案2】:
虽然连接是一种选择,但由于 SQL 注入(尽管可能不会在此处与 DATE 一起使用)和您将要体验的硬解析,我可能会改为探索以下选项。在这种情况下,您将生成更多撤消操作,但您正在执行的操作可能是可以接受的。您还可以添加APPEND 或NOLOGGING 提示,看看是否有帮助。这些提示有一些很好的比较here。
DROP TABLE dba_objects_date;
CREATE OR REPLACE PROCEDURE date_test(date_a IN DATE) AS
sql_stmt VARCHAR2(4000);
BEGIN
sql_stmt := 'create table dba_objects_date as select * from dba_objects a ' ||
'where 0 = 1';
EXECUTE IMMEDIATE sql_stmt;
sql_stmt := 'insert into dba_objects_date select * from dba_objects a ' ||
'where a.created >= :date_from';
EXECUTE IMMEDIATE sql_stmt
USING date_a;
END date_test;
/
BEGIN
date_test(SYSDATE - 14);
END;
/
SELECT COUNT(*)
FROM dba_objects_date;
-- 821