Tek bir ifadede java'da yürütülen birden çok sorgu


100

Merhaba, MySQL sorgu tarayıcısında mümkün olmasına rağmen şu anda bir istisna sağladığından, JDBC'yi kullanarak böyle bir şeyi yürütmenin mümkün olup olmadığını merak ediyordum.

"SELECT FROM * TABLE;INSERT INTO TABLE;"

SQL sorgu dizesinin bölünmesi ve ifadenin iki kez çalıştırılmasıyla mümkün olduğunu fark etsem de, bunun için tek seferlik bir yaklaşım olup olmadığını merak ediyordum.

    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
saklı bir yordama koyarsanız, saklı yordamı arayın. ayrıca bir değişiklik yapmak istediğinizde kodunuzu yeniden dağıtmanız gerekmediği anlamına gelir.
Chris

4
Bağlantı dizesinde ayarlamanız gereken bir özellik var allowMultiQueries=true.
Rahul

olası yineleme:
Java'da

1
Merhaba Rahul, bu proje için eski bir bağlantı nesnesi kullanıyorum ve "allowMultiQueries = true" değerini nerede ayarlamam gerektiğini biliyor musun? Soruya bağlantı nesnesi kodunu
eklediniz

Yanıtlar:


140

JDBC kullanarak böyle bir şeyi yürütmenin mümkün olup olmadığını merak ediyordum.

"SELECT FROM * TABLE;INSERT INTO TABLE;"

Evet mümkün. Bildiğim kadarıyla iki yol var. Onlar

  1. Varsayılan olarak noktalı virgülle ayrılmış birden çok sorguya izin verecek şekilde veritabanı bağlantı özelliğini ayarlayarak.
  2. İmleçleri örtük olarak döndüren bir saklı yordamı çağırarak.

Aşağıdaki örnekler yukarıdaki iki olasılığı göstermektedir.

Örnek 1 : (Birden çok sorguya izin vermek için):

Bir bağlantı isteği gönderirken allowMultiQueries=true, veritabanı url'sine bir bağlantı özelliği eklemeniz gerekir . Bu kişilere ek bağlantı özelliği ise zaten bazı gibi mevcut olduğu autoReConnect=trueiçin vs .. kabul edilebilir değerler allowMultiQueriesmülkiyet vardır true, false, yes, ve no. Diğer herhangi bir değer çalışma zamanında bir SQLException.

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

Böyle bir talimat geçmedikçe, bir SQLExceptionatılır.

execute( String sql )Sorgu yürütmenin sonuçlarını almak için veya diğer varyantlarını kullanmanız gerekir .

boolean hasMoreResultSets = stmt.execute( multiQuerySqlString );

Tekrarlamak ve sonuçları işlemek için aşağıdaki adımlara ihtiyacınız vardır:

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

Örnek 2 : İzlenecek adımlar:

  1. Bir veya daha fazla selectve DMLsorgu içeren bir prosedür oluşturun .
  2. Kullanarak java'dan arayın CallableStatement.
  3. ResultSetProsedürde yürütülen birden fazla sanı yakalayabilirsiniz .
    DML sonuçları yakalanamaz, ancak select
    tablodaki satırların nasıl etkilendiğini bulmak için başka bir sonuç çıkarabilir .

Örnek tablo ve prosedür :

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)

Java'dan Çağrı Prosedürü :

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

Maalesef bu, Derby'nin yerleşik sürümüyle çalışmıyor.
user2428118

@ user2428118: Nedeni? Herhangi bir hata gözlemlendi mi? Sürücünün bu özelliği destekleyip desteklemediğini kontrol ettiniz mi?
Ravinder Reddy

allowMultiQueries = true ekledim ve iyi çalışıyor :)
Hazim

Teşekkürler @RavinderReddy
Siva R

34

Toplu güncellemeyi kullanabilirsiniz, ancak sorgular eylem olmalıdır (yani ekleme, güncelleme ve silme) sorgular

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();

1
Bu yaklaşımı "sprocname ('abc', 984)" sorguları için kullanamazsınız?
sebnukem

18

İpucu: Birden fazla bağlantı mülkünüz varsa, bunları şununla ayırın:

&

Size şöyle bir şey vermek için:

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

Umarım bu birisine yardımcı olur.

Saygılarımızla,

Glyn


11

Testlerime göre, doğru bayrak "allowMultiQueries = true"


2

Neden bunun Stored Procedureiçin bir yazmayı denemiyorsun ?

Çıkabilirsin Result Setve aynı şekilde Stored Procedureistediğini yapabilirsin Insert.

Tek şey de, yeni eklenen satırları almayabilir ise Result Seteğer Insertsonra Select.


1
Her zaman bir Depolanan Prosedür yazma iznine sahip değilsiniz. Örneğin, yalnızca seçim yapmanıza izin verilen bir müşterinin veritabanıdır.
pedram bashiri

2

Sanırım çoklu seçim / güncelleme / ekleme / silme için en kolay yol bu. ExecuteUpdate (str) ile seçimden sonra istediğiniz kadar güncelleme / ekleme / silme çalıştırabilirsiniz (önce bir seçim yapmanız gerekir (gerekirse bir kukla)) (sadece yeni int (count1, count2, ...) kullanın) ve yeni bir seçime ihtiyacınız varsa, 'ifadeyi' ve 'bağlantıyı' kapatın ve sonraki seçim için yenisini yapın. Örnek gibi:

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);
    }

Umut ediyorum bu yardım eder


1
Bir DB bağlantısı açmak çok pahalıdır. Bunu her zaman yapmak iyi bir uygulama değil. Verdiğiniz, n sayıda sorgu için n sayıda DB isabeti yapmalı ve bu da performansın düşmesine yol açmalıdır.
Arun Kumar Mudraboyina
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.