正如评论者所指出的,您的代码无法按预期工作有几个原因。
首先,不要在传递给的字符串中使用分号EXECUTE IMMEDIATE
,因为这样做会给你一个 ORA-00911 'invalid character' 错误:
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 END;
4 /
BEGIN
*
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at line 2
运行后,您可以验证该表是否仍然存在:
SQL> SELECT * FROM SP_AD_B;
no rows selected
(我没有你的表SP_AD_B
,所以我只是创建了一个命名,其中SP_AD_B
包含一个整数列。我没有费心在其中放入任何数据。)
如果您删除字符串内部的分号,而不是外部的分号,它会起作用:
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B';
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> SELECT * FROM SP_AD_B;
SELECT * FROM SP_AD_B
*
ERROR at line 1:
ORA-00942: table or view does not exist
现在表已经消失了,我们在尝试查询它时遇到错误。
希望这应该允许您修复您的脚本,以便它可以工作并删除相关的表。
但是为什么您在输出消息中没有得到任何有用的信息呢?好吧,让我们重新创建SP_AD_B
表,并重新引入分号,然后尝试再次删除表,但使用EXCEPTION
类似于您的处理程序:
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 EXCEPTION
4 WHEN OTHERS THEN
5 dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
6 END;
7 /
Exception, rolling back transaction, SP_AD not resolved.
PL/SQL procedure successfully completed.
在这种情况下,我们收到一条错误消息,告诉我们出了点问题,所以表没有被删除。但是出了什么问题?Oracle 可以报告数以千计的错误,在不知道错误消息的情况下很难猜出问题所在。
您可以在此处采用多种方法。首先,您可以将错误消息SQLERRM
写入dbms_output
:
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 EXCEPTION
4 WHEN OTHERS THEN
5 dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
6 dbms_output.put_line('Error message was: ' || SQLERRM);
7 END;
8 /
Exception, rolling back transaction, SP_AD not resolved.
Error message was: ORA-00911: invalid character
PL/SQL procedure successfully completed.
如果您愿意,还可以使用dbms_utility.format_error_backtrace
将当前堆栈跟踪作为字符串返回。这可能会帮助您找出错误的来源。
或者,您可以重新引发异常。RAISE
在处理程序中单独使用EXCEPTION
会重新引发当前异常:
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 EXCEPTION
4 WHEN OTHERS THEN
5 dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
6 RAISE;
7 END;
8 /
Exception, rolling back transaction, SP_AD not resolved.
BEGIN
*
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at line 6
但是,鉴于您的EXCEPTION
处理程序实际上并没有做任何有用的事情,最好的方法很可能是完全摆脱它。
您的异常处理程序没有实现任何目标,因为您无法提交或回滚 DDL 语句,例如CREATE
、或. 这些语句中的每一个都在运行之前和之后立即发出一个。如果 a成功但 a失败,则无法通过回滚事务来取回已删除的表。我建议摆脱你的and陈述。ALTER
DROP
TRUNCATE
COMMIT
DROP
RENAME
COMMIT WORK
ROLLBACK WORK
最后,评论者 Jeffrey Kemp 注意到了这一行:
SELECT SOURCE INTO source FROM map_switch WHERE ROWNUM = 1;
这会将表中任意行的source
列值赋值给一个变量。可以是任何行;由于您没有指定任何排序,Oracle 可以随意对行进行排序。SOURCE
map_switch
map_switch
如果表中只有一行,那么很清楚您将返回哪一行。但是,如果是这种情况,为什么要指定ROWNUM = 1
?该表是否有不止一行,并且该ROWNUM = 1
部分是否只是为了消除“精确提取返回超过请求的行数”错误?
您最好执行以下操作:
SELECT SOURCE INTO source
FROM (SELECT SOURCE FROM map_switch ORDER BY some_column)
WHERE ROWNUM = 1;
我不知道您的 map_switch
表格中有哪些列,所以我只是在some_column
上面用作其中之一的占位符。如果可能,请选择具有唯一值的列。
请注意,我们不能简单地这样做SELECT ... WHERE ROWNUM = 1 ORDER BY some_column
,因为这会在进行排序之前应用该ROWNUM = 1
子句,并且对单行进行排序的点并不多,因为它只能返回一个顺序。