【问题标题】:Retrieve anonymous PLSQL block result检索匿名 PLSQL 块结果
【发布时间】:2014-11-28 17:50:40
【问题描述】:

在 java 中检索匿名 PLSQL 块的结果时遇到了一些麻烦。

这里是块:

DECLARE
in_cnt_date DATE := '&1';
hv_cnt_id NUMBER := 0;
BEGIN
DBMS_OUTPUT.ENABLE (NULL);
INSERT INTO dt_contexts
(CNT_ID, CNT_CONTEXT, CNT_TYPE, CNT_SOURCE, CNT_COMMENT, CNT_DATE, CNT_DATE_INSERT, CNT_DATE_UPDATE)
VALUES
(0, 'EPE_CONTEXT', 'ROUTE', 'bdd', 'Built from ROUTE', in_cnt_date, SYSDATE, SYSDATE);

SELECT SEQ_DT_CNT_ID.CURRVAL
INTO hv_cnt_id
FROM DUAL;
EXCEPTION WHEN OTHERS THEN RAISE ;
END;

我将该查询放在一个字符串中:

public static final String CONTEXT = "DECLARE in_cnt__date DATE := '&1'; " +
"hv_cnt_id NUMBER := 0; " +
"BEGIN DBMS_OUTPUT.ENABLE (NULL); " +
"INSERT INTO dt_contexts (CNT_ID, CNT_CONTEXT, CNT_TYPE, CNT_SOURCE, CNT_COMMENT, CNT_DATE, CNT_DATE_INSERT, CNT_DATE_UPDATE) " +
"VALUES (0, 'EPE_CONTEXT', 'ROUTE', 'bdd', 'Built from ROUTE', ?, SYSDATE, SYSDATE); " +
"SELECT SEQ_DT_CNT_ID.CURRVAL INTO hv_cnt_id FROM DUAL; " +
"EXCEPTION WHEN OTHERS THEN RAISE ; END;";

那个字符串正确吗?

尝试检索hv_cnt_id的方法:

public int getContextId(Connection conn) throws Exception {
    CallableStatement cs = null;
    ResultSet rs = null;
    int contextId = 0;
    try {
        conn.setAutoCommit(false);
        cs = conn.prepareCall(CONTEXT);
        cs.setDate(1, (java.sql.Date) Route.datePrf);

        cs.execute();
        contextId = (Integer) cs.getObject(1);

        conn.commit();
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    } finally {
        close(rs, cs);
    }
    return contextId;
}

当我收到这条消息时,它不起作用:

java.sql.SQLException: ORA-01858: a non-numeric character was found where a numeric was expected ORA-06512: at line 1

那么我该如何检索hv_cnt_id

【问题讨论】:

  • 删除所有异常处理程序并执行该块,yiu 将看到发生错误的确切行号。
  • 这是因为隐式日期转换失败。添加TO_DATE() 而不是直接将日期字符串分配给日期变量。隐式转换通常取决于会话的NLS_DATE_FORMAT
  • 看起来您正在尝试将参数传递给匿名块,我认为这是不可能的。

标签: java oracle plsql


【解决方案1】:

这是因为 隐式 日期转换失败。添加TO_DATE() 而不是直接将日期字符串分配给日期变量。如果使用java.sql.Date,则不需要TO_DATE()

隐式转换通常取决于会话的NLS_DATE_FORMAT

在您的情况下,in_cnt__date DATE := '&1' 是罪魁祸首。 &1 实际上会尝试转换为日期。因此抛出异常!

public static final String CONTEXT = "DECLARE in_cnt__date DATE := ? ;" +
"hv_cnt_id NUMBER := 0; " +
"BEGIN DBMS_OUTPUT.ENABLE (NULL); " +
"INSERT INTO dt_contexts (CNT_ID, CNT_CONTEXT, CNT_TYPE, CNT_SOURCE, CNT_COMMENT, CNT_DATE, CNT_DATE_INSERT, CNT_DATE_UPDATE) " +
"VALUES (0, 'EPE_CONTEXT', 'ROUTE', 'bdd', 'Built from ROUTE', in_cnt__date, SYSDATE, SYSDATE); " +
"SELECT SEQ_DT_CNT_ID.CURRVAL INTO hv_cnt_id FROM DUAL; " +
"? := hv_cnt_id;
"EXCEPTION WHEN OTHERS THEN RAISE ; END;";

然后,

cs.setDate(1, (java.sql.Date) Route.datePrf);

将为in_cnt__date设置日期;

最后,检索hv_cnt_id 中的值 以下内容已添加到您的 PL/SQL 块中

"? := hv_cnt_id;"

从 JDBC,我们得到它,

 cs.setDate(1, (java.sql.Date) Route.datePrf);
 cs.registerOutParameter(2, Types.NUMBER);
 cs.execute();
 contextId = cs.getInt(2);

【讨论】:

  • 索引有误,还有为什么不对:contextId = cs.getInt(2);?
  • 是的,亚历克斯,你是对的。我只是使用了相同的 OP 代码。
【解决方案2】:

PL/SQL 代码中删除所有exception 处理程序,然后执行该块,您将看到发生错误的确切行号。

Raise 内部异常永远不会让您知道确切的错误详细信息。请阅读http://lalitkumarb.wordpress.com/2014/05/02/when-others-then-null-a-bug/ 关注RAISE 部分。

一旦你这样做了,你会发现有data type转换问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多