2

现在我正在将数据导入并转换到 Oracle 数据库中,如下所示:

  • 程序定期轮询特定文件夹,一旦找到文件,它就会执行一个批处理文件,该文件在 Python 和 bash 中进行一些简单的转换,然后调用 SQL*Loader 将 CSV 文件加载到临时表中。

  • 然后,批处理脚本调用 SQL 脚本(通过 SQLPlus)进行最终转换,并将转换后的数据插入到主表中,用于各自的临时表。

这种方法的问题是在 SQLPlus 端没有错误处理,例如。如果“insert into”语句由于违反约束(或任何其他原因)而失败,它仍将继续执行 SQL 脚本中包含的其余语句。

理想情况下,如果发生任何异常,我希望回滚所有更改并将异常的详细信息插入到 etl 日志表中。

存储过程似乎很合适,因为异常处理是内置的。但是,我在语法上苦苦挣扎——特别是我如何使用我的大 SQL 脚本(它们只是 INSERT INTO、UPDATE、CREATE、DROP、DELETE 等语句的组合)并将它们放入存储过程中基本错误处理。

我希望的是:

  • 一个快速而肮脏的假人指南,用于获取我令人沮丧的 PL/SQL 块并让它在存储过程中执行或
  • 提供相同功能的任何替代方案(如果存储过程不合适),即。一种执行一堆 SQL 语句并在这些语句中的任何一个抛出异常时回滚的方法。

关于我的尝试 - 我尝试将我的 SQL 脚本的一部分复制到存储过程中,但它们总是无法编译并出现错误“PLS-00103 在期望以下之一时遇到符号”。例如。

CREATE OR REPLACE PROCEDURE ETL_2618A AS 
   BEGIN
       DROP SEQUENCE "METER_REPORTING"."SEQ_2618"; 
       CREATE SEQUENCE SEQ_2618; 
END ETL_2618A;

Oracle 文档不是很容易访问,而且我在谷歌搜索/搜索 StackOverflow 方面运气不佳,但如果我遗漏了一些明显的东西,我深表歉意。

4

3 回答 3

3

要在 PL/SQL 中执行 DDL,您需要使用动态 sql。

CREATE OR REPLACE PROCEDURE testProc IS
   s_sql    VARCHAR2(500);
BEGIN
   s_sql := 'DROP SEQUENCE "METER_REPORTING"."SEQ_2618"';
   EXECUTE IMMEDIATE s_sql;


   s_sql := 'CREATE SEQUENCE "METER_REPORTING"."SEQ_2618"';
   EXECUTE IMMEDIATE s_sql;

EXCEPTION

   WHEN OTHERS THEN
       NULL;
end testProc;
/
于 2012-05-31T03:44:25.970 回答
0

如果您在 sqlplus 中运行脚本,您可以使用:

每当 sqlerror

控制发生错误时应该发生的事情。

http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12052.htm

于 2012-05-31T08:42:43.227 回答
0

向 PL/SQL 过程或脚本添加异常处理并不困难,但当然需要一些编码。这是您的程序,添加了一些非常基本的错误报告:

CREATE OR REPLACE PROCEDURE ETL_2618A AS
  nCheckpoint  NUMBER;
BEGIN
  nCheckpoint := 1;

  EXECUTE IMMEDIATE 'DROP SEQUENCE "METER_REPORTING"."SEQ_2618"';

  nCheckpoint := 2;

  EXECUTE IMMEDIATE 'CREATE SEQUENCE SEQ_2618';

  RETURN;
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('ETL_2618A failed at checkpoint ' || nCheckpoint ||
                         ' with error ' || SQLCODE || ' : ' || SQLERRM);
    RAISE;
END ETL_2618A; 

未在动物身上进行测试 - 你会是第一个!:-)

于 2012-05-31T11:24:15.517 回答