Oracle PL/SQL 动态更改变量值的问题
Posted
技术标签:
【中文标题】Oracle PL/SQL 动态更改变量值的问题【英文标题】:Oracle PL/SQL Issue in change the variable value dynamically 【发布时间】:2017-10-10 13:46:06 【问题描述】:我正在尝试使用 Oracle 中的动态查询概念更改查询中的表名。
最初的执行很好。但是一旦用新值修改了表名,即使它显示为旧值。
检查下面的代码......
CREATE OR REPLACE PROCEDURE Test
AS
BEGIN
DECLARE
DELETE_OLD_YEARS NUMBER(2);
RECORD_COUNT NUMBER(10);
INTERVAL_UNIT VARCHAR2(4);
DYNA_QUERY_DEL VARCHAR2(280);
DYNA_TABLE_NAME VARCHAR(30);
BEGIN
INTERVAL_UNIT := 'YEAR';
RECORD_COUNT := 0;
DYNA_TABLE_NAME := 'UserData';
DELETE_OLD_YEARS := 7;
DYNA_QUERY_DEL := 'SELECT COUNT(*)
FROM ' || DYNA_TABLE_NAME || ' UD
WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2))
OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';
-- Delete older than 7 years data
DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData: ' || DYNA_QUERY_DEL);
EXECUTE IMMEDIATE DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
DBMS_OUTPUT.PUT_LINE('Record Count : ' || RECORD_COUNT);
-- Delete older than 7 years data from backup table.
DYNA_TABLE_NAME := 'UserData_Backup';
DELETE_OLD_YEARS := 7;
DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData_Backup : ' || DYNA_QUERY_DEL);
EXECUTE IMMEDIATE DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
DBMS_OUTPUT.PUT_LINE('Record Count 2 : ' || RECORD_COUNT);
END;
END;
/
exec Test;
输出是....
Dynamic Query with UserData : SELECT COUNT(*)
FROM UserData UD
WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2))
OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC
Record Count : 6220
Dynamic Query with UserData_Backup : SELECT COUNT(*)
FROM UserData UD
WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2))
OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC
Record Count 2 : 6220
但是这里的第二个查询应该使用 UserData_Backup 表来准备。
请帮我找出问题....
【问题讨论】:
希望我的解决方案能帮到你..检查一下。!! 您没有更改表名,它已经被硬编码到 DYNA_QUERY_DEL 中。您只更改了不再使用的变量的值。使用动态 SQL 有什么具体原因吗? 【参考方案1】:动态查询将在程序中执行一次,除非您使用 For 循环。如果您不想使用循环,您可以使用相同的查询来进行第二次动态执行,这里我使用的是循环函数。
代码
CREATE OR REPLACE PROCEDURE Test
AS
BEGIN
DECLARE
DELETE_OLD_YEARS NUMBER(2);
RECORD_COUNT NUMBER(10);
INTERVAL_UNIT VARCHAR2(4);
DYNA_QUERY_DEL VARCHAR2(280);
DYNA_TABLE_NAME VARCHAR(30);
BEGIN
INTERVAL_UNIT := 'YEAR';
RECORD_COUNT := 0;
--DYNA_TABLE_NAME := 'UserData';
-- DYNA_TABLE_NAME := 'UserData_Backup';
DELETE_OLD_YEARS := 7;
for c1 in (select 'UserData' as DYNA_TABLE_NAME from dual
union all
select 'UserData_Backup' as DYNA_TABLE_NAME from dual)
loop
DYNA_QUERY_DEL := 'SELECT COUNT(*)
FROM ' || DYNA_TABLE_NAME || ' UD
WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2))
OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';
-- Delete older than 7 years data
DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData: ' || DYNA_QUERY_DEL);
EXECUTE IMMEDIATE DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
RECORD_COUNT := RECORD_COUNT +1;
end loop;
DBMS_OUTPUT.PUT_LINE('Record Count 2 : ' || RECORD_COUNT);
END;
END;
/
exec Test;
【讨论】:
是的,重新分配相同的查询有效。但是我们是否有任何替代方法,例如刷新 DYNA_TABLE_NAME 变量的缓存或会话? 是的...我在代码中更新的备用循环方法检查它。 这对你有帮助吗? 是的,只是寻找替代方法。【参考方案2】:重新分配变量DYNA_QUERY_DEL
尝试这样做
CREATE OR REPLACE PROCEDURE Test
AS
BEGIN
DECLARE
DELETE_OLD_YEARS NUMBER(2);
RECORD_COUNT NUMBER(10);
INTERVAL_UNIT VARCHAR2(4);
DYNA_QUERY_DEL VARCHAR2(280);
DYNA_TABLE_NAME VARCHAR(30);
BEGIN
INTERVAL_UNIT := 'YEAR';
RECORD_COUNT := 0;
DYNA_TABLE_NAME := 'UserData';
DELETE_OLD_YEARS := 7;
DYNA_QUERY_DEL := 'SELECT COUNT(*)
FROM ' || DYNA_TABLE_NAME || ' UD
WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2))
OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';
-- Delete older than 7 years data
DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData: ' || DYNA_QUERY_DEL);
EXECUTE IMMEDIATE DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
DBMS_OUTPUT.PUT_LINE('Record Count : ' || RECORD_COUNT);
-- Delete older than 7 years data from backup table.
DYNA_TABLE_NAME := 'UserData_Backup';
DYNA_QUERY_DEL := 'SELECT COUNT(*)
FROM ' || DYNA_TABLE_NAME || ' UD
WHERE UD.LOGIN_DT < (SYSDATE - NUMTOYMINTERVAL( :1, :2))
OR UD.LOGIN_DT IS NULL ORDER BY UD.LOGIN_DT DESC';
DELETE_OLD_YEARS := 7;
DBMS_OUTPUT.PUT_LINE('Dynamic Query with UserData_Backup : ' || DYNA_QUERY_DEL);
EXECUTE IMMEDIATE DYNA_QUERY_DEL INTO RECORD_COUNT USING DELETE_OLD_YEARS, INTERVAL_UNIT;
DBMS_OUTPUT.PUT_LINE('Record Count 2 : ' || RECORD_COUNT);
END;
END;
/
exec Test;
【讨论】:
是的,我也有同样的想法。但是重新分配对我来说看起来有些奇怪。我是 Java 开发人员,是 PL/SQL 程序的新手。DYNA_TABLE_NAME
的值发生了变化,这就是您需要再次分配DYNA_QUERY_DEL
的原因。无论如何,你能告诉我第二次执行的输出是什么吗?它包含表名UserData_Backup
对吗?
是的,得到了第二个表名。 :-)以上是关于Oracle PL/SQL 动态更改变量值的问题的主要内容,如果未能解决你的问题,请参考以下文章
用PL/SQL Developer导出表数据的时候,窗口一闪而过解决办法