2012-06-13 68 views
0

問題是以下 通過執行SQL加上下面的查詢,一切工作完美:的Java的Oracle JDBC COLUMN語句

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程序中執行這些查詢,我得到值java.sql.SQLException:ORA-00900:第一個SQL查詢無效SQL語句

 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語句中使用它。 例如,第三個查詢是我需要執行的許多查詢之一,並且它們都將具有相同的名字字段

回答

4

column是SQL * Plus命令。它在SQL或PL/SQL中無效,所以不能在Java應用程序中使用它。 像&v_firstname這樣的替換變量也是SQL * Plus結構 - 它們在SQL或PL/SQL中無效,因此您不能在Java應用程序中使用它們。

如果您的目標是在單個查詢中從tbcustomer獲取firstnametbwork的所有列,則需要將兩個表連接起來。假設兩個表有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億次查詢。這將涉及中間層和數據庫服務器之間的大量網絡往返 - 如果您真的擔心性能問題,可以將該工作推送到數據庫中的存儲過程中,旅行。而且你多次執行它的事實讓我懷疑你正在做很多逐行處理,而不是讓數據庫執行基於集合的操作。這也將是表現不佳的主要原因。另外,數據庫天生就可以加入,所以像這樣的簡單連接在假設合適的索引就位的情況下明顯增加了查詢的成本是非常不尋常的。

+0

你好賈斯汀,我熟悉連接方法,這將是我的最後一個選擇。正如我之前提到的,我想要使用的值(名)我將在60個不同的查詢中使用。這60個查詢將執行10 000 000次,所以通過在所有60個查詢中使用連接將影響最終的性能。所以我正在尋找一個選項來獲取名字只有一次,並在所有60個查詢中使用它。該表的大小是非常巨大的,使用某種變量是首選,而不是加入... – vogash

+0

爲了保持客戶id在Java中,並傳遞給查詢也不可能(核心代碼)。任何想法如何無論如何克服列聲明 – vogash

+0

賈斯汀,我發現別的東西:'dbms_session.set_context('my_ctx','v_first_name',(從tbcustomer其中customer_id = 111選擇firstname) select sys_context('my_ctx' ,'v_first_name')from dual'。目前它甚至在SQL Plus中都沒有運行,我認爲DBA應該解決這個問題'ORA-03001:未實現的特性'...但是它可能從java運行它嗎? – vogash