Plsql oracle立即执行,不执行

Plsql oracle立即执行,不执行,plsql,oracle11g,Plsql,Oracle11g,我是Oracle 11gr2的新手,我有以下脚本: BEGIN DECLARE source varchar2(1); BEGIN dbms_output.enable; BEGIN EXECUTE IMMEDIATE 'DROP VIEW SP_AD;'; SELECT SOURCE INTO source FROM map_switch WHERE ROWNUM = 1;

我是Oracle 11gr2的新手,我有以下脚本:

BEGIN
    DECLARE 
        source varchar2(1);

    BEGIN
        dbms_output.enable;


        BEGIN
            EXECUTE IMMEDIATE 'DROP VIEW SP_AD;';
            SELECT SOURCE INTO source FROM map_switch WHERE ROWNUM = 1;
            IF source = 'A' 
                THEN 
                    EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
                    EXECUTE IMMEDIATE 'RENAME TABLE SP_AD_A TO SP_AD;';
                ELSE 
                    EXECUTE IMMEDIATE 'DROP TABLE SP_AD_A;';
                    EXECUTE IMMEDIATE 'RENAME TABLE SP_AD_B TO SP_AD;';
            END IF;
            COMMIT WORK;
                    dbms_output.put_line('SP_AD table issue fixed');
            EXCEPTION
                WHEN OTHERS THEN
                    dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
                    ROLLBACK WORK;
        END;        
    END;
END;
/
本质上,它决定删除哪个表,然后删除视图并重命名另一个表

如果我单独运行这些语句,它工作得非常好,但在上面的脚本中,它返回了成功执行的过程,但没有执行任何操作

我怀疑它是因为某种奇怪的原因而回滚的,但是如果没有回滚,我会犹豫是否执行它这些表的记录超过300000条


有人能告诉我出了什么问题吗?还有,我的异常块有什么问题吗

正如评论者所指出的,代码没有按预期工作有几个原因

首先,不要在传递以立即执行的字符串中使用分号,因为这样做会导致ORA-00911“无效字符”错误:

SQL>开始 2立即执行“DROP TABLE SP_AD_B;”; 3结束; 4 / 开始 * 第1行错误: ORA-00911:无效字符 ORA-06512:在第2行 运行此操作后,您可以验证该表是否仍然存在:

SQL>从SP_AD_B中选择*; 未选择任何行 我没有您的表SP_AD_B,所以我只创建了一个名为SP_AD_B的表,其中有一个整数列。我没有费心在里面放任何数据

如果删除字符串内部的分号,而不是外部的分号,则该操作有效:

SQL>开始 2立即执行“DROP TABLE SP_AD_B”; 3结束; 4 / PL/SQL过程已成功完成。 SQL>从SP_AD_B中选择*; 从SP_AD_B中选择* * 第1行错误: ORA-00942:表或视图不存在 既然表已经不存在了,我们在尝试查询它时会遇到一个错误

希望这能让您修复脚本,使其工作并删除相关表

但是为什么在输出消息中没有得到任何有用的信息呢?好吧,让我们重新创建SP_AD_B表,并重新引入分号,然后再次尝试删除该表,但使用与您类似的异常处理程序:

SQL>开始 2立即执行“DROP TABLE SP_AD_B;”; 3例外情况 4当其他人 5 dbms_输出。put_行“异常,回滚事务,SP_AD未解决”; 6结束; 7 / 异常,回滚事务,SP_AD未解决。 PL/SQL过程已成功完成。 在本例中,我们收到一条错误消息,告诉我们出现了问题,因此表没有被丢弃。但出了什么问题?Oracle可以报告数千个错误,如果不知道错误消息,很难猜测问题所在

在这里,您可以采取多种方法。首先,您可以在SQLERRM中将错误消息写入dbms_输出:

SQL>开始 2立即执行“DROP TABLE SP_AD_B;”; 3例外情况 4当其他人 5 dbms_输出。put_行“异常,回滚事务,SP_AD未解决”; 6dbms_output.put_line的错误消息是:'| | SQLERRM; 7结束; 8 / 异常,回滚事务,SP_AD未解决。 错误消息为:ORA-00911:无效字符 PL/SQL过程已成功完成。 如果愿意,还可以使用以字符串形式返回当前堆栈跟踪。这可能会帮助您找出错误的来源

或者,您可以重新引发异常。在异常处理程序中单独使用RAISE将重新引发当前异常:

SQL>开始 2立即执行“DROP TABLE SP_AD_B;”; 3例外情况 4当其他人 5 dbms_输出。put_行“异常,回滚事务,SP_AD未解决”; 6提高; 7结束; 8 / 异常,回滚事务,SP_AD未解决。 开始 * 第1行错误: ORA-00911:无效字符 ORA-06512:在第6行 然而,考虑到您的异常处理程序实际上并没有做任何有帮助的事情,最好的方法很可能是将其完全去掉

您的异常处理程序无法实现任何功能,因为您无法提交或回滚DDL语句,如CREATE、ALTER、DROP或TRUNCATE。这些语句中的每一条都会在运行前后立即发出COMMIT。如果删除成功但重命名失败,则无法通过回滚事务来恢复删除的表。我建议您放弃提交工作和回滚工作语句

最后,评论员Jeffrey Kemp注意到这句话:

SELECT SOURCE INTO source FROM map_switch WHERE ROWNUM = 1;
这会将来自表map_开关的某个任意行的列source的值指定给名为source的变量。可以是任何争吵;由于您没有指定任何排序,Oracle可以随意对map_开关的行进行排序

如果表中只有一行,那么返回哪一行就很清楚了。但是,如果是这种情况,为什么要指定ROWNUM=1?该表是否有多行,并且ROWNUM=1部分是否正好用于使“精确获取”返回的num多于请求的num 行的错误

您最好执行以下操作:

SELECT SOURCE INTO source
  FROM (SELECT SOURCE FROM map_switch ORDER BY some_column)
 WHERE ROWNUM = 1;
我不知道map_switch表中有哪些列,所以我只是使用上面的某个_列作为其中一个的占位符。如果可能,请选择具有唯一值的列


请注意,我们不能简单地选择。。。其中ROWNUM=1按某个列排序,因为在进行排序之前会应用ROWNUM=1子句,并且对单个行排序没有太多意义,因为它只能返回一个顺序。

从动态查询中删除终止分号!不能回滚DDL语句。它们也不需要提交。异常块的一个错误是,当其他异常发生时,您捕获了所有异常,但您没有将消息写入dbms_输出或重新发送它。添加一行,例如dbms_output.put_line'Error was'| | SQLERRM;例外的情况是,其他人会告诉你问题出在哪里。@LukeWoodward那会是什么样子?为什么只从map_开关中检索第一条记录?这就是代码的味道,因为它是不确定的。谢谢!现在,这是一个课本答案,应该是所有答案的模板。我希望我能投更多的票