Beberapa kueri dieksekusi di java dalam satu pernyataan

100

Hai Saya bertanya-tanya apakah mungkin untuk menjalankan sesuatu seperti ini menggunakan JDBC karena saat ini memberikan pengecualian meskipun mungkin di browser kueri MySQL.

"SELECT FROM * TABLE;INSERT INTO TABLE;"

Meskipun saya menyadari bahwa itu mungkin dengan memiliki string kueri SQL yang dipisahkan dan pernyataan dieksekusi dua kali tetapi saya bertanya-tanya apakah ada pendekatan satu kali untuk ini.

    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);
MilindaD
sumber
1
dimasukkan ke dalam prosedur tersimpan, panggil prosedur tersimpan. berarti Anda juga tidak perlu menerapkan ulang kode Anda saat ingin membuat perubahan.
Chris
4
Ada properti yang harus Anda setel dalam string koneksi allowMultiQueries=true.
Rahul
kemungkinan duplikat: Bagaimana cara mengeksekusi kueri sql komposit di java? [1] [1]: stackoverflow.com/questions/6773393/…
prayagupd
1
Hai Rahul, untuk proyek ini saya menggunakan objek koneksi lama biasa dan apakah Anda tahu di mana saya harus menyetel "allowMultiQueries = true". Telah menambahkan kode objek koneksi dalam pertanyaan
MilindaD

Jawaban:

140

Saya bertanya-tanya apakah mungkin untuk mengeksekusi sesuatu seperti ini menggunakan JDBC.

"SELECT FROM * TABLE;INSERT INTO TABLE;"

Ya itu mungkin. Ada dua cara, sejauh yang saya tahu. Mereka

  1. Dengan mengatur properti koneksi database untuk memperbolehkan beberapa kueri, dipisahkan oleh titik koma secara default.
  2. Dengan memanggil prosedur tersimpan yang mengembalikan kursor secara implisit.

Contoh berikut menunjukkan dua kemungkinan di atas.

Contoh 1 : (Untuk mengizinkan banyak kueri):

Saat mengirim permintaan koneksi, Anda perlu menambahkan properti koneksi allowMultiQueries=trueke url database. Ini adalah properti koneksi tambahan untuk mereka jika sudah ada beberapa, seperti autoReConnect=true, dll .. nilai yang dapat diterima untuk allowMultiQueriesproperti yang true, false, yes, dan no. Nilai lain apa pun ditolak pada waktu proses dengan SQLException.

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

Kecuali instruksi seperti itu diberikan, an SQLExceptiondilempar.

Anda harus menggunakan execute( String sql )atau varian lainnya untuk mengambil hasil eksekusi kueri.

boolean hasMoreResultSets = stmt.execute( multiQuerySqlString );

Untuk mengulangi dan memproses hasil, Anda memerlukan langkah-langkah berikut:

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

Contoh 2 : Langkah-langkah untuk diikuti:

  1. Buat prosedur dengan satu atau lebih select, dan DMLkueri.
  2. Sebut saja dari java menggunakan CallableStatement.
  3. Anda dapat menangkap beberapa gambar yang ResultSetdieksekusi dalam prosedur.
    Hasil DML tidak dapat ditangkap tetapi dapat mengeluarkan hasil lain select
    untuk menemukan bagaimana baris terpengaruh dalam tabel.

Tabel sampel dan prosedur :

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)

Prosedur Panggilan dari Java :

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
Ravinder Reddy
sumber
Sayangnya, ini tidak berfungsi dengan versi Derby yang disematkan.
pengguna2428118
@ user2428118: Alasan? Ada kesalahan yang diamati? Apakah Anda sudah memeriksa apakah Driver mendukung fitur ini?
Ravinder Reddy
saya telah menambahkan allowMultiQueries = true dan berfungsi dengan baik :)
Hazim
Terima kasih @RavinderReddy
Siva R
34

Anda dapat menggunakan pembaruan Batch tetapi kueri harus berupa kueri tindakan (yaitu menyisipkan, memperbarui, dan menghapus)

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();
Himanshu Mohta
sumber
1
Anda tidak dapat menggunakan pendekatan ini untuk kueri "panggil sprocname ('abc', 984)"?
sebnukem
18

Petunjuk: Jika Anda memiliki lebih dari satu properti koneksi, pisahkan dengan:

&

Untuk memberi Anda sesuatu seperti:

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

Saya harap ini membantu seseorang.

Salam,

Glyn

Glyn
sumber
11

Berdasarkan pengujian saya, bendera yang benar adalah "allowMultiQueries = true"

muye
sumber
2

Mengapa Anda tidak mencoba dan menulis Stored Procedureuntuk ini?

Anda bisa Result Setkeluar dan dalam hal yang sama Stored ProcedureAnda bisa mendapatkan Insertapa yang Anda inginkan.

Satu-satunya hal adalah Anda mungkin tidak mendapatkan baris yang baru disisipkan di Result Setjika Anda Insertsetelah Select.

JHS
sumber
1
Anda tidak selalu memiliki izin untuk menulis Prosedur Tersimpan. Misalnya, itu adalah database klien yang hanya boleh Anda pilih.
pedram bashiri
2

Saya rasa ini adalah cara termudah untuk multy selection / update / insert / delete. Anda dapat menjalankan pembaruan / sisipkan / hapus sebanyak yang Anda inginkan setelah memilih (Anda harus membuat pilihan terlebih dahulu (dummy jika diperlukan)) dengan mengeksekusiUpdate (str) (cukup gunakan int baru (count1, count2, ...)) dan jika Anda membutuhkan pilihan baru, tutup 'pernyataan' dan 'koneksi' dan buat yang baru untuk pilihan berikutnya. Seperti contoh:

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

Saya harap ini membantu

Alexandros Topalidis
sumber
1
Membuka koneksi DB sangat mahal. Bukan praktik yang baik melakukan itu setiap saat. Yang telah Anda berikan harus membuat n jumlah hit DB untuk n jumlah query yang mengarah ke kinerja yang buruk.
Arun Kumar Mudraboyina