एकल कथन में जावा में निष्पादित कई प्रश्न


100

नमस्ते मैं सोच रहा था कि क्या JDBC का उपयोग करके इस तरह से कुछ करना संभव है क्योंकि यह वर्तमान में एक अपवाद प्रदान करता है भले ही यह MySQL क्वेरी ब्राउज़र में संभव हो।

"SELECT FROM * TABLE;INSERT INTO TABLE;"

जबकि मुझे एहसास है कि एसक्यूएल क्वेरी स्ट्रिंग के विभाजन और दो बार निष्पादित किए गए बयान के साथ यह संभव है, लेकिन मैं सोच रहा था कि क्या इसके लिए एक समय दृष्टिकोण है।

    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
एक संग्रहीत प्रक्रिया में डाल दिया, संग्रहीत कार्यविधि को कॉल करें। जब आप बदलाव करना चाहते हैं तो आपको अपने कोड को फिर से नहीं करना होगा।
क्रिस

4
एक संपत्ति है जिसे आपको कनेक्शन स्ट्रिंग में सेट करना होगा allowMultiQueries=true
राहुल

संभावित डुप्लिकेट: जावा में कम्पोजिट
सीक्वल क्वेश्चन

1
हाय राहुल, इस परियोजना के लिए मैं एक सादे पुराने कनेक्शन ऑब्जेक्ट का उपयोग कर रहा हूं और क्या आप जानते हैं कि मुझे "allowMultiQueries = true" कहां सेट करना चाहिए। प्रश्न में कनेक्शन ऑब्जेक्ट कोड जोड़ा है
मिलिंडा

जवाबों:


140

मैं सोच रहा था कि क्या जेडीबीसी का उपयोग करके इस तरह से कुछ करना संभव है।

"SELECT FROM * TABLE;INSERT INTO TABLE;"

हाँ यह संभव है। जहां तक ​​मुझे पता है, दो तरीके हैं। वो हैं

  1. डिफ़ॉल्ट रूप से अर्ध-बृहदान्त्र द्वारा अलग-अलग, कई प्रश्नों की अनुमति देने के लिए डेटाबेस कनेक्शन संपत्ति सेट करके।
  2. एक संग्रहीत प्रक्रिया को कॉल करके जो कर्सर को निहित करता है।

निम्नलिखित उदाहरण उपरोक्त दो संभावनाओं को प्रदर्शित करते हैं।

उदाहरण 1 : (कई प्रश्नों की अनुमति देने के लिए):

कनेक्शन अनुरोध भेजते समय, आपको allowMultiQueries=trueडेटाबेस url में कनेक्शन संपत्ति संलग्न करना होगा। यह उन लोगों के लिए अतिरिक्त कनेक्शन संपत्ति यदि पहले से मौजूद कुछ, की तरह है autoReConnect=true, के लिए आदि .. स्वीकार्य मान allowMultiQueriesसंपत्ति हैं true, false, yes, और no। किसी भी अन्य मान को रनटाइम पर अस्वीकार कर दिया जाता है a 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
  3. आप ResultSetप्रक्रिया में निष्पादित कई एस पर कब्जा कर सकते हैं ।
    DML परिणाम कैप्चर नहीं किए जा सकते, लेकिन select
    तालिका में पंक्तियों के प्रभावित होने का पता लगाने के लिए एक और जारी कर सकते हैं।

नमूना तालिका और प्रक्रिया :

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

दुर्भाग्य से, यह डर्बी के एम्बेडेड संस्करण के साथ काम नहीं करता है।
user2428118

@ user2428118: कारण? कोई त्रुटि देखी गई? क्या आपने जांचा कि ड्राइवर इस सुविधा का समर्थन करता है या नहीं?
रविंदर रेड्डी

मैंने allowMultiQueries = true जोड़ा है और ठीक काम करता है :)
Hazim

धन्यवाद @RavinderReddy
Siva R

34

आप बैच अपडेट का उपयोग कर सकते हैं, लेकिन प्रश्नों पर कार्रवाई होनी चाहिए (यानी सम्मिलित करें, अपडेट करें और हटाएं) प्रश्न

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
आप "कॉल स्पोकनाम ('एबीसी', 984)" प्रश्नों के लिए इस दृष्टिकोण का उपयोग नहीं कर सकते हैं?
sebnukem

18

संकेत: यदि आपके पास एक से अधिक कनेक्शन संपत्ति है, तो उन्हें अलग करें:

&

आपको कुछ देने के लिए जैसे:

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

मुझे उम्मीद है इससे किसी को सहायता मिलेगी।

सादर,

ग्लिन


11

मेरे परीक्षण के आधार पर, सही झंडा "AllowMultiQueries = true" है


2

आप इसके लिए प्रयास क्यों नहीं करते Stored Procedure?

आप Result Setबाहर निकल सकते हैं और उसी में Stored Procedureआप Insertजो चाहें कर सकते हैं।

केवल एक चीज यह है कि Result Setअगर आप के Insertबाद में नई सम्मिलित पंक्तियाँ नहीं मिल सकती हैं Select


1
आपके पास हमेशा संग्रहीत प्रक्रिया लिखने की अनुमति नहीं है। उदाहरण के लिए, यह एक ग्राहक का डेटाबेस है जिसे आपको केवल चयन करने की अनुमति है।
पेड्रम बशीरी

2

मुझे लगता है कि यह मल्टी सिलेक्शन / अपडेट / इंसर्ट / डिलीट का सबसे आसान तरीका है। आप सेलेक्ट के बाद कई अपडेट / इंसर्ट / डिलीट कर सकते हैं जैसे आप चाहते हैं (आपको पहले एक सेलेक्ट करना होगा (एक डमी यदि आवश्यक हो तो) निष्पादित करें (स्ट्रैट) के साथ (सिर्फ नया इंट (काउंट 1, काउंट 2, ...) का उपयोग करें) और यदि आपको एक नए चयन की आवश्यकता है तो 'स्टेटमेंट' और 'कनेक्शन' को बंद करें और अगले चयन के लिए नया बनाएं। उदाहरण की तरह:

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
एक DB कनेक्शन खोलना बहुत महंगा है। हर बार ऐसा करने का अच्छा अभ्यास नहीं है। जो आपने दिया है वह n संख्या डीबी हिट के लिए एन प्रश्नों की संख्या के लिए बनाता है जो खराब प्रदर्शन की ओर जाता है।
अरुण कुमार मुदराबोइना
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.