【问题标题】:Calling Oracle "DEFINE" from Java从 Java 调用 Oracle “DEFINE”
【发布时间】:2012-07-09 07:18:46
【问题描述】:

我需要在 Oracle 中定义一些变量,以便在我们应用程序的数据库安装脚本中进一步使用。基本上,我们的安装程序现在的工作方式是读取脚本文件并通过 Java 中的 JDBC 调用每个文件。我需要让 Oracle 在数据库端进行变量替换,因为有过程、触发器、创建语句等需要引用它们(比如“CREATE TABLE &&MYSCHEMA.TBL_NAME ...”)。

我遇到的问题是 DEFINE 语句在从 Java 调用时抛出错误(示例):

private static void testDefineVariables() {
    String url = "jdbc:oracle:thin:@localhost:1521:LOCALDEV";
    String username = "SYSTEM";
    String password = "manager42";
    Connection conn = null;
    Statement stmt = null;
    try {
        conn = DriverManager.getConnection(url, username, password);
        stmt = conn.createStatement();

        //Execute the sql
        stmt.execute("DEFINE MYSCHEMA='TESTSCHEMA'");

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    finally {
        try {

        if(stmt != null)
            stmt.close();

        if(conn != null)
            conn.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

错误是:

java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:194)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1000)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1882)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1847)
at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:301)

我正在使用带有 ojdbc6-11.2.0.1.0.jar JDBC 驱动程序的 Oracle 11g R2 数据库。我能够从 sqldeveloper 工具以及 SQLPlus 控制台成功执行该语句,但不能从 Java 应用程序执行。我需要在数据库驱动程序上配置其他属性吗?我可以从该驱动程序进行这种类型的调用吗?

我知道有些人可能会立即建议在 Java 端使用变量绑定,但这不是一个选项。这些脚本需要可以从 SQL 界面和安装程序中执行。除了这个,还有其他原因,我就不一一赘述了。

我也希望让它与 sql-maven-plugin 一起工作,但基于这个 JIRA 可能无法实现:

Add Oracle SQLPlus syntax for substitution variables

如果有人有任何建议或知道如何让它发挥作用,我将不胜感激。

【问题讨论】:

    标签: java sql oracle jdbc oracle11g


    【解决方案1】:

    我认为 DEFINE 不能在 SQLPLUS 之外工作 - JAVA 使用 JDBC 并假设 execute() 的参数是有效的 SQL。如果你能够 在 SQLPLUS 之外使用 DEFINE 这意味着您正在使用的实用程序是 旨在与 SQLPLUS 兼容或部分替代。

    DEFINE 是一个 SQLPLUS 命令 - SQLPLUS 是一个 ORACLE 实用程序。

    根据这个 URL 定义不是 SQL 语句

    http://www.adp-gmbh.ch/ora/sqlplus/define.html

    【讨论】:

    • 谢谢。我有一种感觉是这种情况,但我不确定。
    【解决方案2】:

    DEFINE 和替换变量语法&&MYSCHEMA.TBL_NAME 都是 SQL*Plus 命令。它们不是有效的 SQL 或 PL/SQL 构造。您将无法通过 JDBC 按原样使用它们。

    取决于你说你不想进入的原因

    • 您的 Java 应用程序可以调用操作系统来调用 SQL*Plus 并传入脚本
    • 您的 Java 应用程序可以实现脚本所依赖的任何 SQL*Plus 功能。您的应用程序不需要执行DEFINE MYSCHEMA='TESTSCHEMA',而是需要维护一个HashMap,它将myschema 之类的变量映射到TESTSCHEMA 之类的值。然后,您的应用程序必须解析各个 SQL 语句以查找类似 @​​987654327@ 的文本,将其替换为其本地 HashMap 中的值,然后将生成的 SQL 字符串发送到数据库服务器。根据您需要复制多少 SQL*Plus 功能,这可能是一项相当重要的工作。许多 PL/SQL IDE(例如 Toad 或 SQL Developer)实现了 SQL*Plus 功能的一个子集——我不知道有任何人尝试过实现所有最后的 SQL*Plus 功能。

    【讨论】:

      猜你喜欢
      • 2012-10-20
      • 1970-01-01
      • 2016-05-27
      • 1970-01-01
      • 2012-01-27
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多