我有这段代码:
BEGIN
FOR
U1 IN (SELECT * FROM SOME_USER.SOME_TABLE)
LOOP
BEGIN
-- do something;
END;
END LOOP;
END;
我的问题是有时SOME_USER.SOMETABLE
不存在,但我希望运行脚本的其余部分。我知道在运行代码之前(在IF ... THEN
块中)检查表是否存在是行不通的,因为在编译时会评估SELECT * FROM SOME_USER.SOME_TABLE
。
另一个途径是使用SELECT
运行EXECUTE IMMEDIATE
。这样它将在运行时进行评估,我将能够捕获异常。很遗憾,我找不到使用EXECUTE IMMEDIATE
循环U1 IN
的方法。我该如何实现这个目标?
我使用的是Oracle 11g,SQL脚本是从Windows上的批处理脚本运行的。
答案 0 :(得分:4)
您可以使用the 'OPEN FOR' syntax:
DECLARE
CUR SYS_REFCURSOR;
<variables or record type> -- declare as appropriate
BEGIN
OPEN CUR FOR 'SELECT * FROM SOME_USER.SOME_TABLE';
LOOP
FETCH CUR INTO <variables or record type>;
EXIT WHEN CUR%NOTFOUND;
-- do something with variables or record
END LOOP;
CLOSE CUR;
END;
/
您需要将每一行提取到变量或记录类型中,您不能使用%ROWTYPE
,因为该表仍然不存在;如果适合您的数据量,您可以更改为批量提取。
如果你运行它仍然会得到ORA-00942,但如果这是在存储的程序中,你将无法在运行时获得它,现在你可以添加一个IF
块来检查表格存在于OPEN
之前。
拥有一个数据模型,其中对象在运行时可能存在或不存在,但看起来很可疑......
答案 1 :(得分:0)
您可以使用解决方法 - 创建嵌套表类型并将SELECT结果存储在其中。使用该类型循环遍历值。
所以,
SELECT data_obj(COL1, COL2) bulk collect into data_tbl_typ from data_table;
这部分可以进入动态sql。 (记得使用绑定变量)
然后在您的过程中循环遍历此嵌套表类型。
答案 2 :(得分:0)
使用DBMS_SQL包运行查询。
按照此Oracle文档中的示例进行操作:
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#sthref6147
答案 3 :(得分:-1)
pl / sql有异常条款。其他几乎所有东西都有。您可以在函数中处理异常,或者打印消息并将其传递回main。将你的功能分解成更小的功能,让每个功能都能抓住它自己的例外。
BEGIN
FOR
U1 IN (SELECT * FROM SOME_USER.SOME_TABLE)
LOOP
BEGIN
-- do something;
END;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('Oh well. The table isn't there.');
--RAISE;
END;