【问题标题】:Java Oracle jdbc COLUMN statementJava Oracle jdbc COLUMN 语句
【发布时间】:2012-06-13 16:36:56
【问题描述】:

问题如下 通过在 SQL Plus 中执行以下查询,一切正常:

column firstname new_value v_firstname
select firstname from tbcustomer where customer_id = 111
select '&v_firstname', wrk.* from tbwork where customer_id = 111

但是当我尝试从 Java 程序执行这些查询时,我在第一个 SQL 查询中得到 java.sql.SQLException: ORA-00900: invalid SQL statement

        Connection connection = null;
    Statement stat = null;
    String query = "column due_date new_value v_due_date";
    try {

        // Load the JDBC driver
        String driverName = "oracle.jdbc.driver.OracleDriver";
        Class.forName(driverName);
        connection = DriverManager.getConnection(url, username, password);
        stat = connection.createStatement();
        boolean res_num = stat.execute(query);

    } catch (ClassNotFoundException e) {
        // Could not find the database driver
    } catch (SQLException e) {
        e.printStackTrace();
    }

现在的问题是如何克服这个错误并执行第一个查询,或者您是否有任何其他解决方案可以在 oracle 会话上定义变量并在其他 SQL 语句中使用它。 例如,第三个查询是我需要执行的众多查询之一,它们都将具有相同的名字字段

【问题讨论】:

    标签: java oracle variables jdbc


    【解决方案1】:

    column 是一个 SQL*Plus 命令。它在 SQL 或 PL/SQL 中无效,因此您不能在 Java 应用程序中使用它。 像 &v_firstname 这样的替换变量也是一个 SQL*Plus 构造——它们在 SQL 或 PL/SQL 中无效,因此您不能在 Java 应用程序中使用它们。

    如果您的目标是在单个查询中从 tbcustomer 获取 firstname 以及从 tbwork 获取所有列,则需要连接这两个表。假设两个表都有一个customer_id 列,这就是这两个表应该如何连接

    SELECT cust.firstname,
           work.*
      FROM tbcustomer cust
           JOIN tbwork work ON (cust.customer_id = work.customer_id)
     WHERE cust.customer_id = 111
    

    假设您将针对多个 customer_id 值执行此查询,但是,111 应该是绑定变量而不是文字,并且您的 Java 代码应该使用 PreparedStatement 来准备 SQL 语句,然后绑定在执行查询之前使用setInt 方法获取类似 111 的值。

    如果你想把它分成两个数据库调用,你可以简单地做类似的事情

    PreparedStatement stmtGetFirstName = connection.prepareStatement("select firstname from tbcustomer where customer_id = ?");
    stmtGetFirstName.setInt( 1, 111 );
    ResultSet rsGetFirstName = stmtGetFirstName.executeQuery();
    String firstName = rsGetFirstName.getString();
    
    PreparedStatement stmtGetWork = connection.prepareStatement("select ?, work.* from tbwork where customer_id = ?");
    stmtGetWork.setString( 1, firstName );
    stmtGetWork.setInt( 2, 111 );
    ResultSet rsGetWork = stmtGetWork.executeQuery();
    

    如果您可以保证所有 6 亿次执行都将发生在同一个数据库会话中,那么您可以使用数据库上下文。您需要创建上下文和它在数据库中使用的包

    SQL> create or replace context fname_ctx using scott.pkg_get_fname;
    
    Context created.
    
    SQL> ed
    Wrote file afiedt.buf
    
      1  create or replace package pkg_get_fname
      2  is
      3    procedure set_fname( p_customer_id in number );
      4    function get_fname return varchar2;
      5* end;
    SQL> /
    
    Package created.
    
    SQL> create or replace package body pkg_get_fname
      2  is
      3    procedure set_fname( p_customer_id in number )
      4    as
      5    begin
             -- Obviously, you'd get the data here from your table rather than hard-coding 'Bob'
      6      dbms_session.set_context( 'fname_ctx', 'fname', 'Bob' );
      7    end;
      8
      9    function get_fname
     10      return varchar2
     11    is
     12      l_fname varchar2(100);
     13    begin
     14      l_fname := sys_context( 'fname_ctx', 'fname' );
     15      return l_fname;
     16    end;
     17  end;
     18  /
    
    Package body created.
    

    然后,您可以在 Java 中调用 pkg_get_fname.set_fname(111) 来设置上下文并在查询中使用函数 pkg_get_fname.get_fname

    然而,关注性能并计划从 Java 对数据库执行 6 亿次查询似乎很奇怪。这将涉及中间层和数据库服务器之间的大量网络往返——如果你真的关心性能,你会将这项工作推送到数据库中的存储过程以消除网络循环——旅行。而且您多次执行它们的事实使我怀疑您正在进行大量的逐行处理,而不是让数据库进行基于集合的操作。这也将成为业绩不佳的主要原因。此外,数据库生来就是为了连接,因此假设有适当的索引,像这样的简单连接会显着增加查询成本是很不寻常的。

    【讨论】:

    • 你好贾斯汀,我熟悉加入方法,这将是我最后的选择。正如我之前提到的,我将在 60 个不同的查询中使用我想要使用的值(名字)。这 60 个查询将被执行 10 000 000 次,因此在所有 60 个查询中使用 join 最终会影响性能。因此,我正在寻找仅获取一次名字并在所有 60 个查询中使用它的选项。表的大小非常大,最好使用某种变量而不是连接...
    • 在java中保留客户ID并将其传递给查询也是不可能的(核心代码)。知道如何克服列语句的问题
    • 贾斯汀,我发现了别的东西:dbms_session.set_context('my_ctx', 'v_first_name', (select firstname from tbcustomer where customer_id = 111)) select sys_context('my_ctx', 'v_first_name') from dual。目前它甚至在 SQL Plus 中也没有运行,我认为 DBA 应该解决这个问题ORA-03001: unimplemented feature... 但是可以从 java 运行它吗?
    • @user662249 - 如果您想将查询分成两个单独的部分以及如果您想使用数据库上下文,我使用 Java 方法更新了我的答案。我想我不明白你怎么可能用 Java 编写代码来执行它,但又不可能添加一个额外的变量来存储名称。而且我怀疑您正在尝试进行逐行处理,而不是进行更有效的基于集合的处理——如果您关心性能,请让数据库以集合的形式工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多