需要在ORACLE中EXECUTE IMMEDIATE语句中使用的where子句中使用动态变量
Need to use dynamic variables in where clause used in EXECUTE IMMEDIATE statement in ORACLE
ORACLE(使用 SQL 开发人员)。
我需要正确构造 EXECUTE IMMEDIATE 语句。
我没有 "create" 权限。任务是为 tables/dates 的动态列表获取每个日期每个 table 的行数。
我有以下内容:
DECLARE CURSOR cur_table_name IS SELECT TABLE_NAME
FROM ALL_TABLES WHERE TABLE_NAME IN ('table_a', 'table_b', 'table_c');
CURSOR cur_BEGIN_DATE IS
select to_date('2014-09-25 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + rownum -1 AS BEGIN_DATE,
to_date('2014-09-26 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + rownum -1 AS END_DATE from dual
Connect by level <= to_date('2014-09-30 00:00:00', 'YYYY-MM-DD HH24:MI:SS') - to_date('2014-09-25 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + 1;
var_total_rows NUMBER(15);
var_table_name VARCHAR2 (50);
var_bgn_date DATE;
var_end_date DATE;
BEGIN
OPEN cur_TABLE_NAME;
LOOP
FETCH cur_TABLE_NAME INTO var_table_name;
EXIT WHEN cur_TABLE_NAME%NOTFOUND;
--testing output
DBMS_OUTPUT.PUT_LINE ('Table: '|| var_table_name);
var_total_rows :=0;
OPEN cur_BEGIN_DATE;
LOOP
FETCH cur_BEGIN_DATE INTO var_bgn_date, var_end_date;
EXIT WHEN cur_BEGIN_DATE%NOTFOUND;
--TESTING OUTPUT
DBMS_OUTPUT.PUT_LINE ('DATES ARE: ' || var_bgn_date || ', ' ||var_end_date|| ' Table IS: '||var_table_name);
--------THIS IS THE NOT WORKING STATEMENT DUE TO VARIABLES IN THE WHERE STATEMENT:
execute immediate 'SELECT COUNT(*) FROM '||var_table_name || ' where DTM >= '|| var_bgn_date ||' and DTM < '||var_end_date INTO var_total_rows;
DBMS_OUTPUT.PUT_LINE (var_table_name||' '||var_bgn_date||' '||var_end_date ||' '||var_total_rows);
END LOOP;
CLOSE cur_BEGIN_DATE;
END LOOP;
CLOSE cur_TABLE_NAME;
结束;
如果我从 where 语句中删除变量(只需执行 'Select * from || var_table_name into var_total_rows; )就可以了。如果 where 子句中有一个静态值 - 它可以工作(但循环使用相同的日期,我需要更改日期!)。但是我无法使语法适用于 where 子句中的动态变量。
这能做到吗?
感谢您的帮助!
您的 var_bgn_date
和 var_end_date
变量是 DATE 类型的,但作为不带引号的字符串插入到动态语句中,具有基于会话 NLS_DATE_FORMAT 值的隐式格式。你会得到一个生成的语句,如:
SELECT COUNT(*) FROM table_a where DTM >= 2014-09-25 00:00:00 and DTM < 2014-09-26 00:00:00
您可以添加转义单引号以将其转换为有效语句,但仍然依赖使用相同 NLS 设置的隐式转换:
EXECUTE immediate 'SELECT COUNT(*) FROM '||var_table_name
|| ' where DTM >= '''|| var_bgn_date ||''' and DTM < '''||var_end_date ||''''
INTO var_total_rows;
这将生成:
SELECT COUNT(*) FROM table_a where DTM >= '2014-09-25 00:00:00' and DTM < '2014-09-26 00:00:00'
但实际上您应该使用绑定变量来避免与字符串之间的任何转换:
EXECUTE immediate 'SELECT COUNT(*) FROM '||var_table_name
|| ' where DTM >= :bgn_date and DTM < :end_date'
INTO var_total_rows
USING var_bgn_date, var_end_date;
ORACLE(使用 SQL 开发人员)。 我需要正确构造 EXECUTE IMMEDIATE 语句。 我没有 "create" 权限。任务是为 tables/dates 的动态列表获取每个日期每个 table 的行数。 我有以下内容:
DECLARE CURSOR cur_table_name IS SELECT TABLE_NAME
FROM ALL_TABLES WHERE TABLE_NAME IN ('table_a', 'table_b', 'table_c');
CURSOR cur_BEGIN_DATE IS
select to_date('2014-09-25 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + rownum -1 AS BEGIN_DATE,
to_date('2014-09-26 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + rownum -1 AS END_DATE from dual
Connect by level <= to_date('2014-09-30 00:00:00', 'YYYY-MM-DD HH24:MI:SS') - to_date('2014-09-25 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + 1;
var_total_rows NUMBER(15);
var_table_name VARCHAR2 (50);
var_bgn_date DATE;
var_end_date DATE;
BEGIN
OPEN cur_TABLE_NAME;
LOOP
FETCH cur_TABLE_NAME INTO var_table_name;
EXIT WHEN cur_TABLE_NAME%NOTFOUND;
--testing output
DBMS_OUTPUT.PUT_LINE ('Table: '|| var_table_name);
var_total_rows :=0;
OPEN cur_BEGIN_DATE;
LOOP
FETCH cur_BEGIN_DATE INTO var_bgn_date, var_end_date;
EXIT WHEN cur_BEGIN_DATE%NOTFOUND;
--TESTING OUTPUT
DBMS_OUTPUT.PUT_LINE ('DATES ARE: ' || var_bgn_date || ', ' ||var_end_date|| ' Table IS: '||var_table_name);
--------THIS IS THE NOT WORKING STATEMENT DUE TO VARIABLES IN THE WHERE STATEMENT:
execute immediate 'SELECT COUNT(*) FROM '||var_table_name || ' where DTM >= '|| var_bgn_date ||' and DTM < '||var_end_date INTO var_total_rows;
DBMS_OUTPUT.PUT_LINE (var_table_name||' '||var_bgn_date||' '||var_end_date ||' '||var_total_rows);
END LOOP;
CLOSE cur_BEGIN_DATE;
END LOOP;
CLOSE cur_TABLE_NAME;
结束;
如果我从 where 语句中删除变量(只需执行 'Select * from || var_table_name into var_total_rows; )就可以了。如果 where 子句中有一个静态值 - 它可以工作(但循环使用相同的日期,我需要更改日期!)。但是我无法使语法适用于 where 子句中的动态变量。 这能做到吗?
感谢您的帮助!
您的 var_bgn_date
和 var_end_date
变量是 DATE 类型的,但作为不带引号的字符串插入到动态语句中,具有基于会话 NLS_DATE_FORMAT 值的隐式格式。你会得到一个生成的语句,如:
SELECT COUNT(*) FROM table_a where DTM >= 2014-09-25 00:00:00 and DTM < 2014-09-26 00:00:00
您可以添加转义单引号以将其转换为有效语句,但仍然依赖使用相同 NLS 设置的隐式转换:
EXECUTE immediate 'SELECT COUNT(*) FROM '||var_table_name
|| ' where DTM >= '''|| var_bgn_date ||''' and DTM < '''||var_end_date ||''''
INTO var_total_rows;
这将生成:
SELECT COUNT(*) FROM table_a where DTM >= '2014-09-25 00:00:00' and DTM < '2014-09-26 00:00:00'
但实际上您应该使用绑定变量来避免与字符串之间的任何转换:
EXECUTE immediate 'SELECT COUNT(*) FROM '||var_table_name
|| ' where DTM >= :bgn_date and DTM < :end_date'
INTO var_total_rows
USING var_bgn_date, var_end_date;