【问题标题】:How to execute this Oracle statement on JDBC如何在 JDBC 上执行这个 Oracle 语句
【发布时间】:2014-09-28 01:29:46
【问题描述】:

我在使用 JDBC 准备语句执行以下操作时遇到问题:

CREATE OR REPLACE TRIGGER Time_trg BEFORE INSERT ON Time FOR EACH ROW 
BEGIN 
  SELECT Time_seq.NEXTVAL INTO :new.id FROM dual; 
END;

代码:

try {
   PreparedStatement statement = connection.prepareStatement( sql );
   preparedStatement.executeUpdate();
} finally {
   statement.close();
}

我收到此错误:

java.sql.SQLException: Missing IN or OUT parameter at index:: 1

我正在研究与数据库无关的解决方案,因此我需要一些可移植的东西。那么oracle的问题是什么?

【问题讨论】:

  • 问题是 PreparedStatement 的命名参数语法与 Oracle 的 :new 语法冲突,PreparedStatement 中的命名参数无法转义。所以你用 Statement 而不是 PreparedStatement 来颠覆这个小问题。

标签: java oracle jdbc


【解决方案1】:

不需要编写我们自己的存储过程来执行此操作。 Oracle 提供了一个内置的存储过程我们可以使用:DBMS_UTILITY.EXEC_DDL_STATEMENT:

 DBMS_UTILITY.EXEC_DDL_STATEMENT('create table t1 (id number)');

事实上,这比the workaround procedure suggested in the accepted answer 更安全,因为它不允许执行 DML,因此可以防止 SQL 注入

【讨论】:

    【解决方案2】:

    使用oracle.jdbc.OraclePreparedStatement

    OraclePreparedStatement statement = (OraclePreparedStatement)connection.prepareStatement( sql );
    

    由于这是特定于 Oracle 的,因此常规的 PrepareStatement 没有帮助。 Oracle 为其提供了一个包装器,还具有其他功能。

    同样,Oracle 提供的OracleCallableStatement 类似于CallableStatement

    解决方法:(当必须使用 PreparedStatement - 被滥用的风险

     CREATE PROCEDURE EXECUTE_MY_DDL(INSTRING VARCHAR2)
     AS
     BEGIN
        EXECUTE IMMEDIATE INSTRING;
     END;
    

    Reference JavaDoc

    【讨论】:

    • 感谢您的回答,但我需要一个便携式解决方案。我不想使用 OraclePreparedStatement,因为它不适用于任何其他数据库。还能做什么?
    • 很遗憾,您不能这样做,因为:something 有特殊含义。您可以尝试将此字符串传递给 PL/SQL 块 else.. 使用 EXECUTE IMMEDIATE .. 虽然不是一个干净的修复。
    • 原来我在后台使用 OraclePreparedStatement。堆栈跟踪在其上显示 OraclePreparedStatement。似乎如果我使用它,那么我必须针对该 API 做一些特定的事情才能使其工作。那会是什么?
    • OraclePreparedStatement 应该可以工作,但是您尝试执行的操作是在此处使用PreparedStatement
    • Well PreparedStatement 是 jdbc 驱动程序作者实现的接口,事实证明 Oracle 返回的具体类是 OraclePreparedStatementWrapper,它使用 OraclePreparedStatement,因此从技术上讲,我正在使用它。因此,如果我必须使用 OraclePreparedStatement,我假设有一个特殊的 API 我必须调用它才能工作,否则我正在做的事情会起作用。
    【解决方案3】:

    既然在 Oracle DDL 中不能有任何绑定变量,为什么要使用PreparedStatement?您可以改用静态语句,不会遇到这个问题:

    try (Statement s = connection.createStatement()) {
        s.executeUpdate(sql);
    }
    

    【讨论】:

      猜你喜欢
      • 2017-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-06
      • 2014-12-16
      • 1970-01-01
      相关资源
      最近更新 更多