JDBC में इन्सर्ट आईडी कैसे प्राप्त करें?


385

मैं INSERTजावा में JDBC का उपयोग करके एक डेटाबेस (जो मेरे मामले में Microsoft SQL सर्वर है) में रिकॉर्ड करना चाहता हूं । उसी समय, मैं सम्मिलित आईडी प्राप्त करना चाहता हूं। JDBC API का उपयोग करके मैं इसे कैसे प्राप्त कर सकता हूं?


उस आईडी को छोड़ दें जो क्वेरी में String sql = "INSERT INTO 'yash'.'mytable' ('name') VALUES (?)"; int primkey = 0 ; PreparedStatement pstmt = con.prepareStatement(sql, new String[] { "id" }/*Statement.RETURN_GENERATED_KEYS*/); pstmt.setString(1, name); if (pstmt.executeUpdate() > 0) { java.sql.ResultSet generatedKeys = pstmt.स्वतःप्राप्त की गई है GetGeneratedKeys (); if (generatedKeys.next()) primkey = generatedKeys.getInt(1); }
यश

जवाबों:


650

यदि यह एक ऑटो जनरेट की है, तो आप इसके लिए उपयोग कर सकते हैं Statement#getGeneratedKeys()। आपको इसे उसी Statementरूप में कॉल करने की आवश्यकता है जिस तरह से इसका उपयोग किया जा रहा है INSERT। आप पहले की जरूरत कथन का उपयोग बनाने के लिएStatement.RETURN_GENERATED_KEYS JDBC ड्राइवर को सूचित करने के चाबियाँ वापस जाने के लिए।

यहाँ एक मूल उदाहरण दिया गया है:

public void create(User user) throws SQLException {
    try (
        Connection connection = dataSource.getConnection();
        PreparedStatement statement = connection.prepareStatement(SQL_INSERT,
                                      Statement.RETURN_GENERATED_KEYS);
    ) {
        statement.setString(1, user.getName());
        statement.setString(2, user.getPassword());
        statement.setString(3, user.getEmail());
        // ...

        int affectedRows = statement.executeUpdate();

        if (affectedRows == 0) {
            throw new SQLException("Creating user failed, no rows affected.");
        }

        try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
            if (generatedKeys.next()) {
                user.setId(generatedKeys.getLong(1));
            }
            else {
                throw new SQLException("Creating user failed, no ID obtained.");
            }
        }
    }
}

ध्यान दें कि आप JDBC ड्राइवर पर निर्भर हैं कि यह काम करता है या नहीं। वर्तमान में, अधिकांश अंतिम संस्करण काम करेंगे, लेकिन अगर मैं सही हूं, तो ओरेकल जेडीबीसी ड्राइवर अभी भी इसके साथ कुछ परेशान है। MySQL और DB2 ने पहले ही उम्र के लिए इसका समर्थन किया था। PostgreSQL ने बहुत समय पहले इसका समर्थन करना शुरू कर दिया था। मैं MSSQL के बारे में टिप्पणी नहीं कर सकता क्योंकि मैंने इसका उपयोग कभी नहीं किया।

ओरेकल के लिए, आप अंतिम उत्पन्न कुंजी प्राप्त करने के लिए एक ही लेनदेन में सीधे CallableStatementएक RETURNINGक्लॉज या SELECT CURRVAL(sequencename)(या जो भी डीबी-विशिष्ट सिंटैक्स ऐसा करने के लिए) के साथ आमंत्रित कर सकते हैं INSERTइस उत्तर को भी देखें ।


4
डालने से पहले एक अनुक्रम में अगला मूल्य प्राप्त करना बेहतर है, क्योंकि डालने के बाद वक्र प्राप्त करने के लिए, क्योंकि उत्तरार्द्ध एक बहु-थ्रेडेड वातावरण (जैसे, किसी वेब ऐप कंटेनर) में गलत मान वापस कर सकता है। JTDS MSSQL ड्राइवर getGeneratedKeys का समर्थन करता है।
JeeBee

4
(स्पष्ट करना चाहिए कि मैं आमतौर पर ओरेकल का उपयोग करता हूं, इसलिए सामान्य रूप से जेडीबीसी चालक की क्षमताओं की बहुत कम अपेक्षाएं हैं)।
JeeBee

7
स्टेटमेंट सेट नहीं करने का एक दिलचस्प साइड-इफेक्ट। RETURN_GENERATED_KEYS विकल्प त्रुटि संदेश है, जो पूरी तरह से अस्पष्ट है "किसी भी परिणाम प्राप्त करने से पहले कथन को निष्पादित किया जाना चाहिए।"
क्रिस विंटर्स

7
generatedKeys.next()रिटर्न trueअगर डीबी एक जनरेट की गई कुंजी लौट आए। देखिए, यह ए ResultSetclose()बस मुक्त संसाधनों है। अन्यथा आपका डीबी लंबे समय तक उनमें से बाहर चला जाएगा और आपका आवेदन टूट जाएगा। आपको बस कुछ यूटिलिटी मेथड लिखना होगा जो क्लोजिंग टास्क करता है। यह भी देखें इस और इस सवाल का जवाब।
बालुसक

5
अधिकांश डेटाबेस / ड्राइवरों के लिए सही उत्तर। ओरेकल के लिए यह काम नहीं करता है। Oracle के लिए, इसमें बदलें: connection.prepareStatement (sql, new String [] {"PK कॉलम नाम"});
डेरेल टेग

24
  1. उत्पन्न कॉलम बनाएँ

    String generatedColumns[] = { "ID" };
  2. अपने बयान में इस जीनियस कॉलम को पास करें

    PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
  3. ResultSetस्टेटमेंट पर जनरेट किए गए को लाने के लिए ऑब्जेक्ट का उपयोग करें

    ResultSet rs = stmtInsert.getGeneratedKeys();
    
    if (rs.next()) {
        long id = rs.getLong(1);
        System.out.println("Inserted ID -" + id); // display inserted record
    }

8

मैं Microsoft SQL Server 2008 R2 को एक सिंगल-थ्रेडेड JDBC- आधारित एप्लिकेशन से हिट कर रहा हूं और RETURN_GENERATED_KEYS प्रॉपर्टी या किसी भी रेडीएडस्टेटमेंट का उपयोग किए बिना अंतिम आईडी को वापस खींच रहा हूं। कुछ इस तरह दिखता है:

private int insertQueryReturnInt(String SQLQy) {
    ResultSet generatedKeys = null;
    int generatedKey = -1;

    try {
        Statement statement = conn.createStatement();
        statement.execute(SQLQy);
    } catch (Exception e) {
        errorDescription = "Failed to insert SQL query: " + SQLQy + "( " + e.toString() + ")";
        return -1;
    }

    try {
        generatedKey = Integer.parseInt(readOneValue("SELECT @@IDENTITY"));
    } catch (Exception e) {
        errorDescription = "Failed to get ID of just-inserted SQL query: " + SQLQy + "( " + e.toString() + ")";
        return -1;
    }

    return generatedKey;
} 

यह ब्लॉग पोस्ट तीन मुख्य SQL सर्वर "अंतिम आईडी" विकल्पों को अलग करता है: http://msjawahar.wordpress.com/2008/01/25/how-to-find-the-last-identity-value-inserted-in-the -sql- सर्वर / - अभी तक अन्य दो की जरूरत नहीं है।


4
यह कि आवेदन में केवल एक धागा है, जो रेस की स्थिति को असंभव नहीं बनाता है: यदि दो क्लाइंट एक पंक्ति सम्मिलित करते हैं और अपनी विधि से आईडी प्राप्त करते हैं, तो यह विफल हो सकता है।
11684

आप क्यों? मुझे खुशी है कि मैं बहुत गरीब नहीं हूँ, जो कई धागों की अनुमति देते समय आपके कोड को डीबग करना पड़ता है!
मग्गाडर्ड

6

उपयोग करते समय एक 'असमर्थित सुविधा' त्रुटि का सामना करते हुए Statement.RETURN_GENERATED_KEYS, यह प्रयास करें:

String[] returnId = { "BATCHID" };
String sql = "INSERT INTO BATCH (BATCHNAME) VALUES ('aaaaaaa')";
PreparedStatement statement = connection.prepareStatement(sql, returnId);
int affectedRows = statement.executeUpdate();

if (affectedRows == 0) {
    throw new SQLException("Creating user failed, no rows affected.");
}

try (ResultSet rs = statement.getGeneratedKeys()) {
    if (rs.next()) {
        System.out.println(rs.getInt(1));
    }
    rs.close();
}

BATCHIDऑटो जनरेट आईडी कहां है।


आपका मतलब हैBATCHID
MoolsBytheway

बहुत बढ़िया जवाब!!!
हसीथा जयवर्धना

3

मैं SQLServer 2008 का उपयोग कर रहा हूं , लेकिन मेरे पास एक विकास सीमा है: मैं इसके लिए एक नए ड्राइवर का उपयोग नहीं कर सकता, मुझे "com.microsoft.jdbc.sqlserver.SQLServerDriver" का उपयोग करना होगा (मैं इस com.microsoft.sqlserver.jdbc का उपयोग नहीं कर सकता हूं .SQLServerDriver ")।

इसलिए समाधान conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)ने मेरे लिए एक java.lang.AbstractMethodError फेंक दिया । इस स्थिति में, एक संभावित समाधान जो मुझे मिला है वह Microsoft द्वारा सुझाया गया पुराना है: JDBC का उपयोग करके @@ पहचान मूल्य कैसे प्राप्त करें

import java.sql.*; 
import java.io.*; 

public class IdentitySample
{
    public static void main(String args[])
    {
        try
        {
            String URL = "jdbc:microsoft:sqlserver://yourServer:1433;databasename=pubs";
            String userName = "yourUser";
            String password = "yourPassword";

            System.out.println( "Trying to connect to: " + URL); 

            //Register JDBC Driver
            Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();

            //Connect to SQL Server
            Connection con = null;
            con = DriverManager.getConnection(URL,userName,password);
            System.out.println("Successfully connected to server"); 

            //Create statement and Execute using either a stored procecure or batch statement
            CallableStatement callstmt = null;

            callstmt = con.prepareCall("INSERT INTO myIdentTable (col2) VALUES (?);SELECT @@IDENTITY");
            callstmt.setString(1, "testInputBatch");
            System.out.println("Batch statement successfully executed"); 
            callstmt.execute();

            int iUpdCount = callstmt.getUpdateCount();
            boolean bMoreResults = true;
            ResultSet rs = null;
            int myIdentVal = -1; //to store the @@IDENTITY

            //While there are still more results or update counts
            //available, continue processing resultsets
            while (bMoreResults || iUpdCount!=-1)
            {           
                //NOTE: in order for output parameters to be available,
                //all resultsets must be processed

                rs = callstmt.getResultSet();                   

                //if rs is not null, we know we can get the results from the SELECT @@IDENTITY
                if (rs != null)
                {
                    rs.next();
                    myIdentVal = rs.getInt(1);
                }                   

                //Do something with the results here (not shown)

                //get the next resultset, if there is one
                //this call also implicitly closes the previously obtained ResultSet
                bMoreResults = callstmt.getMoreResults();
                iUpdCount = callstmt.getUpdateCount();
            }

            System.out.println( "@@IDENTITY is: " + myIdentVal);        

            //Close statement and connection 
            callstmt.close();
            con.close();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        try
        {
            System.out.println("Press any key to quit...");
            System.in.read();
        }
        catch (Exception e)
        {
        }
    }
}

इस समाधान ने मेरे लिए काम किया!

आशा है कि ये आपकी मदद करेगा!


1

नई सम्मिलित आईडी प्राप्त करने के लिए आप निम्न जावा कोड का उपयोग कर सकते हैं।

ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, quizid);
ps.setInt(2, userid);
ps.executeUpdate();

ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
    lastInsertId = rs.getInt(1);
}

0

एक टिप्पणी के बजाय , मैं सिर्फ पोस्ट का जवाब देना चाहता हूं।


इंटरफ़ेस java.sql.PreparedStatement

  1. columnIndexes «आप columnIndexes और SQL स्टेटमेंट को स्वीकार करने वाले readyStatement फ़ंक्शन का उपयोग कर सकते हैं। जहां कॉलमइंडेक्स ने निरंतर झंडे की अनुमति दी है वहां कथन .ETURN_GENERATED_KEYS 1 या कथन. NO_GENERATED_KEYS [2], SQL कथन जिसमें एक या अधिक हो सकते हैं? '' पैरामीटर प्लेसहोल्डर।

    वाक्य - विन्यास "

    Connection.prepareStatement(String sql, int autoGeneratedKeys)
    Connection.prepareStatement(String sql, int[] columnIndexes)

    उदाहरण:

    PreparedStatement pstmt = 
        conn.prepareStatement( insertSQL, Statement.RETURN_GENERATED_KEYS );

  1. columnNames « जैसे स्तंभों की सूची बनाएं 'id', 'uniqueID', ...। उस लक्ष्य तालिका में, जिसमें स्वतः-जनरेट की गई कुंजी होती है जिसे वापस लौटाया जाना चाहिए। यदि SQL कथन नहीं है, तो ड्राइवर उन्हें अनदेखा करेगा INSERT

    वाक्य - विन्यास "

    Connection.prepareStatement(String sql, String[] columnNames)

    उदाहरण:

    String columnNames[] = new String[] { "id" };
    PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );

पूर्ण उदाहरण:

public static void insertAutoIncrement_SQL(String UserName, String Language, String Message) {
    String DB_URL = "jdbc:mysql://localhost:3306/test", DB_User = "root", DB_Password = "";

    String insertSQL = "INSERT INTO `unicodeinfo`( `UserName`, `Language`, `Message`) VALUES (?,?,?)";
            //"INSERT INTO `unicodeinfo`(`id`, `UserName`, `Language`, `Message`) VALUES (?,?,?,?)";
    int primkey = 0 ;
    try {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        Connection conn = DriverManager.getConnection(DB_URL, DB_User, DB_Password);

        String columnNames[] = new String[] { "id" };

        PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );
        pstmt.setString(1, UserName );
        pstmt.setString(2, Language );
        pstmt.setString(3, Message );

        if (pstmt.executeUpdate() > 0) {
            // Retrieves any auto-generated keys created as a result of executing this Statement object
            java.sql.ResultSet generatedKeys = pstmt.getGeneratedKeys();
            if ( generatedKeys.next() ) {
                primkey = generatedKeys.getInt(1);
            }
        }
        System.out.println("Record updated with id = "+primkey);
    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    }
}

0

Hibernate के NativeQuery के साथ, आपको SingleResult के बजाय एक ResultList को वापस करना होगा, क्योंकि Hibernate एक देशी क्वेरी को संशोधित करता है

INSERT INTO bla (a,b) VALUES (2,3) RETURNING id

पसंद

INSERT INTO bla (a,b) VALUES (2,3) RETURNING id LIMIT 1

यदि आप एक एकल परिणाम प्राप्त करने की कोशिश करते हैं, जो अधिकांश डेटाबेस (कम से कम PostgreSQL) को एक सिंटैक्स त्रुटि फेंकने का कारण बनता है। बाद में, आप सूची से परिणामी आईडी ला सकते हैं (जिसमें आमतौर पर एक आइटम होता है)।


0

यह सामान्य के साथ भी उपयोग करना संभव है Statement(न केवल PreparedStatement)

Statement statement = conn.createStatement();
int updateCount = statement.executeUpdate("insert into x...)", Statement.RETURN_GENERATED_KEYS);
try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
  if (generatedKeys.next()) {
    return generatedKeys.getLong(1);
  }
  else {
    throw new SQLException("Creating failed, no ID obtained.");
  }
}

0

मेरे मामले में ->

ConnectionClass objConnectionClass=new ConnectionClass();
con=objConnectionClass.getDataBaseConnection();
pstmtGetAdd=con.prepareStatement(SQL_INSERT_ADDRESS_QUERY,Statement.RETURN_GENERATED_KEYS);
pstmtGetAdd.setString(1, objRegisterVO.getAddress());
pstmtGetAdd.setInt(2, Integer.parseInt(objRegisterVO.getCityId()));
int addId=pstmtGetAdd.executeUpdate();              
if(addId>0)
{
    ResultSet rsVal=pstmtGetAdd.getGeneratedKeys();
    rsVal.next();
    addId=rsVal.getInt(1);
}

फिर भी मुझे लगता है कि इसे पाने के लिए यह लंबा दृष्टिकोण है। मुझे लगता है कि अधिक संपीड़ित समाधान भी होगा।
दशा

0

यदि आप स्प्रिंग JDBC का उपयोग कर रहे हैं, तो आप सम्मिलित आईडी प्राप्त करने के लिए स्प्रिंग के जेनरेट किए गए फ़ोल्डर का उपयोग कर सकते हैं।

यह उत्तर देखें ... स्प्रिंग Jdbctemplate.update (स्ट्रिंग sql, obj ... arj) का उपयोग करके सम्मिलित आईडी कैसे प्राप्त करें


-6
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret  = st.execute();

क्षमा करें, लेकिन यह क्या माना जाता है?
मूलबेटीवे

1. इस createStatementविधि से Connectionकिसी भी परम की उम्मीद नहीं है। 2. executeसे विधि Statementकी उम्मीद है एक क्वेरी के साथ एक स्ट्रिंग। 3. executeविधि लौटती है: trueयदि पहला परिणाम एक ResultSetवस्तु है; falseयदि यह एक अद्यतन गणना है या कोई परिणाम नहीं हैं। docs.oracle.com/javase/7/docs/api/java/sql/…
atilacamurca
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.