我们有一个问题,需要一个糟糕的黑客来解决。让我给你一些背景信息:
我们有一个应用程序在卸载/重新安装它时会覆盖客户配置设置。它安装时使用默认值,覆盖客户输入的任何设置。
管理层的解决方案是创建两个脚本,每个步骤一个:
在卸载应用程序之前,创建一个临时表并将配置设置复制到其中。
重新安装应用后,将临时表中的值复制回原始表格以保留其设置。
我不太喜欢他们的解决方案,但我必须坚持下去。
我有第1步,但我在处理第二个脚本(第2步)的情况时遇到问题,而没有先运行第一个脚本(步骤1)。
实质上,当第二个脚本编译时,如果不同部门中的其他人忘记运行第一个脚本,则临时表将不存在。
这是我目前用于第二个脚本的代码。
DECLARE
lvnTableExists NUMBER(1);
lvbTempTableCopied BOOLEAN;
lvsTempTable VARCHAR2(21) := 'TEMP_TABLE';
BEGIN
-- CalcTypVarValue Table Copy
SELECT COUNT(*)
INTO lvnTableExists
FROM ALL_TABLES x
WHERE x.Table_Name = lvsTempTable ;
IF lvnTableExists = 1 THEN
FOR CalcRow IN (SELECT * FROM Temp_Table) LOOP -- Temp_Table will not exist if first script didn't run, causing a compile error
UPDATE SomeOtherTable c
SET c.foo= CalcRow.foo,
c.bar= CalcRow.bar,
c.DateLastMaint = SYSDATE
WHERE c.bob= CalcRow.bob
AND c.bill= CalcRow .bill;
END LOOP;
lvbTempTableCopied := TRUE;
ELSE
lvbTempTableCopied := FALSE;
END IF;
EXCEPTION
WHEN OTHERS THEN
...
...
我的问题是,如果Temp_Table
根本不存在,那么我将收到编译时错误,因此脚本根本不会运行。我需要它才能运行,所以如果基于lvbTempTableCopied
的表不存在,我可以就是否做其他事情采取行动。
我听说过用FOR CalcRow IN (EXECUTE IMMEDIATE 'SELECT * FROM ' || lvsTempTable)
之类的东西绕过它,但我不能在FOR IN LOOP
之内使用它。
我如何使用EXECUTE IMMEDIATE
来绕过编译时错误?
答案 0 :(得分:2)
您可以使用REF CURSOR动态执行此操作,请参阅下面的示例代码,
DECLARE
TYPE cur_typ IS REF CURSOR;
c cur_typ;
v_table_exists VARCHAR2(1);
type temp1_rec is record (col1 VARCHAR2(100), col2 VARCHAR2(100));
v_temp temp1_rec;
BEGIN
SELECT 'Y'
INTO v_table_exists
FROM all_tables
WHERE table_name = 'TEMP1';
--dynamic query with parameters
OPEN c FOR 'SELECT col1, col2 FROM temp1 WHERE :param1=:param2' USING 'PARAM1', 'PARAM1' ;
LOOP
FETCH c INTO v_temp;
EXIT WHEN c%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_temp.col1);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
/
CREATE TABLE TEMP1
(COL1 VARCHAR2(100),
col2 VARCHAR2(100));
INSERT INTO temp1
VALUES('123123123asdfasdfsfa', 'JHASDKLFJLASDFLAS');