2012-05-29 94 views
70

您好我想知道是否有可能使用JDBC執行類似這樣的事情,因爲它目前提供了一個例外,即使它可能在MySQL查詢瀏覽器中。在單個語句中在java中執行多個查詢

"SELECT FROM * TABLE;INSERT INTO TABLE;" 

雖然我不知道這是可能的具有兩倍SQL查詢字符串被分裂和執行的語句,但我想知道是否有這個一次性的做法。

String url = "jdbc:mysql://localhost:3306/"; 
    String dbName = "databaseinjection"; 
    String driver = "com.mysql.jdbc.Driver"; 
    String sqlUsername = "root"; 
    String sqlPassword = "abc"; 

    Class.forName(driver).newInstance(); 

    connection = DriverManager.getConnection(url+dbName, sqlUsername, sqlPassword); 
+1

放入存儲過程,調用存儲過程。意味着當您想要更改時,您也不必重新部署代碼。 – Chris

+3

有一個屬性必須在連接字符串'allowMultiQueries = true'中設置。 – Rahul

+0

可能重複:如何在java中執行復合sql查詢?[1] [1]:http://stackoverflow.com/questions/6773393/how-to-execute-composite-sql-queries-in-java – prayagupd

回答

100

我想知道它是否能夠執行這樣的使用JDBC。

"SELECT FROM * TABLE;INSERT INTO TABLE;" 

是的,這是可能的。據我所知,有兩種方法。它們是:

  1. 通過設置數據庫連接屬性以允許多個查詢, 默認情況下用分號分隔。
  2. 通過調用返回遊標隱式的存儲過程。

以下示例說明了上述兩種可能性。

實施例1:(爲了允許多個查詢):

雖然發送連接請求,則需要一個連接屬性allowMultiQueries=true追加到數據庫URL。這是如果已經存在一些額外的連接屬性,如autoReConnect=true等。allowMultiQueries屬性的可接受值爲true,false,yesno。任何其他值在運行時會被拒絕,其中包括SQLException

String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true"; 

除非這樣的指令通過,否則引發SQLException

您必須使用execute(String sql)或其他變體來獲取查詢執行的結果。

boolean hasMoreResultSets = stmt.execute(multiQuerySqlString); 

要遍歷和處理結果你需要以下步驟:

READING_QUERY_RESULTS: // label 
    while (hasMoreResultSets || stmt.getUpdateCount() != -1) { 
     if (hasMoreResultSets) { 
      Resultset rs = stmt.getResultSet(); 
      // handle your rs here 
     } // if has rs 
     else { // if ddl/dml/... 
      int queryResult = stmt.getUpdateCount(); 
      if (queryResult == -1) { // no more queries processed 
       break READING_QUERY_RESULTS; 
      } // no more queries processed 
      // handle success, failure, generated keys, etc here 
     } // if ddl/dml/... 

     // check to continue in the loop 
     hasMoreResultSets = stmt.getMoreResults(); 
    } // while results 

實施例2:執行步驟:

  1. 與一種或多種select創建過程,並且DML查詢。
  2. 使用CallableStatement從Java調用它。
  3. 您可以捕捉過程中執行多個ResultSet秒。
    DML結果不能被捕獲,但可發出另一select
    找到行如何在表的影響。

樣品表和過程:從Java

mysql> create table tbl_mq(i int not null auto_increment, name varchar(10), primary key (i)); 
Query OK, 0 rows affected (0.16 sec) 

mysql> delimiter // 
mysql> create procedure multi_query() 
    -> begin 
    -> select count(*) as name_count from tbl_mq; 
    -> insert into tbl_mq(names) values ('ravi'); 
    -> select last_insert_id(); 
    -> select * from tbl_mq; 
    -> end; 
    -> // 
Query OK, 0 rows affected (0.02 sec) 
mysql> delimiter ; 
mysql> call multi_query(); 
+------------+ 
| name_count | 
+------------+ 
|   0 | 
+------------+ 
1 row in set (0.00 sec) 

+------------------+ 
| last_insert_id() | 
+------------------+ 
|    3 | 
+------------------+ 
1 row in set (0.00 sec) 

+---+------+ 
| i | name | 
+---+------+ 
| 1 | ravi | 
+---+------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

呼叫過程:

CallableStatement cstmt = con.prepareCall("call multi_query()"); 
boolean hasMoreResultSets = cstmt.execute(); 
READING_QUERY_RESULTS: 
    while (hasMoreResultSets) { 
     Resultset rs = stmt.getResultSet(); 
     // handle your rs here 
    } // while has more rs 
+0

不幸的是,這不適用於Derby的嵌入式版本。 – user2428118

+0

@ user2428118:原因?觀察到任何錯誤?你有沒有檢查Driver是否支持這個功能? –

+0

我已經添加了allowMultiQueries = true並且工作正常:) – Hazim

0

爲什麼不試試爲此寫一個Stored Procedure

你可以得到Result Set出和在同一Stored Procedure你可以Insert你想要的。

唯一可能的是,如果您在Select之後Insert之後,您可能無法獲得Result Set中新插入的行。

21

您可以使用批量更新,但是查詢必須採取行動(即插入,更新和刪除)查詢

Statement s = c.createStatement(); 
String s1 = "update emp set name='abc' where salary=984"; 
String s2 = "insert into emp values ('Osama',1420)"; 
s.addBatch(s1); 
s.addBatch(s2);  
s.executeBatch(); 
+0

不能使用這種方法爲「呼叫sprocname(‘ABC’,984)」查詢? – sebnukem

7

根據我的測試,正確的標誌爲 「allowMultiQueries =真正的」

12

提示:如果你有一個以上的連接到ction屬性然後將它們帶獨立:

& 

爲了給你的財產以後這樣的:

url="jdbc:mysql://localhost/glyndwr?autoReconnect=true&allowMultiQueries=true" 

我希望這可以幫助其他人。

問候,

格林

0

我認爲這是對MULTY選擇/更新/插入/刪除的最簡單的方法。您可以運行許多更新/插入/刪除如u想後,選擇(你必須做出一個選擇第一(虛擬如果需要的話))方法executeUpdate(STR)(只需使用新的INT(COUNT1,COUNT2,...))如果你需要一個新的選擇關閉「聲明」和「連接」,併爲下一次選擇做出新的選擇。例如像:

String str1 = "select * from users"; 
String str9 = "INSERT INTO `port`(device_id, potition, port_type, di_p_pt) VALUE ('"+value1+"', '"+value2+"', '"+value3+"', '"+value4+"')"; 
String str2 = "Select port_id from port where device_id = '"+value1+"' and potition = '"+value2+"' and port_type = '"+value3+"' "; 
try{ 
    Class.forName("com.mysql.jdbc.Driver").newInstance(); 
    theConnection=(Connection) DriverManager.getConnection(dbURL,dbuser,dbpassword); 
    theStatement = theConnection.prepareStatement(str1); 
    ResultSet theResult = theStatement.executeQuery(); 
    int count8 = theStatement.executeUpdate(str9); 
    theStatement.close(); 
    theConnection.close(); 
    theConnection=DriverManager.getConnection(dbURL,dbuser,dbpassword); 
    theStatement = theConnection.prepareStatement(str2); 
    theResult = theStatement.executeQuery(); 

    ArrayList<Port> portList = new ArrayList<Port>(); 
    while (theResult.next()) { 
     Port port = new Port(); 
     port.setPort_id(theResult.getInt("port_id")); 

     portList.add(port); 
    } 

我希望它能幫助

+1

打開數據庫連接非常昂貴。每次都不是很好的做法。您提供的應該爲n個查詢導致n個數據庫命中,導致性能較差。 –

相關問題