Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

अद्वितीय कॉलम वाली तालिका में पंक्तियाँ जोड़ना:मौजूदा आईडी मान और नए बनाए गए मान प्राप्त करें

बैच INSERTs को संभालते समय यह पहला दृष्टिकोण JDBC ड्राइवर के व्यवहार के बारे में कोई धारणा नहीं बनाता है। यह

. द्वारा संभावित INSERT त्रुटियों से बचा जाता है
  • किसी भी मौजूदा mail_id के लिए तालिका से पूछताछ करना हमारे वर्तमान डेटा सेट में मान,
  • संबंधित id को नोट करता है उन mail_id . के लिए मान मान जो मौजूद हैं,
  • mail_id को INSERT करता है वे मान जो मौजूद नहीं हैं, और उनके (नए) id . को पुनः प्राप्त करते हैं मान, और फिर
  • पंक्तियों को दूसरी तालिका में सम्मिलित करता है (inv_table )।
try (Connection dbConn = DriverManager.getConnection(myConnectionString, "root", "usbw")) {
    dbConn.setAutoCommit(false);

    // test data and setup
    Long aid = 123L;
    List<MailidInvitation> invitationList = new ArrayList<MailidInvitation>();
    invitationList.add(new MailidInvitation(13L));
    invitationList.add(new MailidInvitation(11L));
    invitationList.add(new MailidInvitation(12L));
    // remove stuff from previous test run
    try (Statement s = dbConn.createStatement()) {
        s.executeUpdate("DELETE FROM mail_contacts WHERE mail_id IN (11,13)");
    }
    try (PreparedStatement ps = dbConn.prepareStatement(
            "DELETE FROM inv_table WHERE aid=?")) {
        ps.setLong(1, aid);
        ps.executeUpdate();
    }

    // real code starts here
    //
    // create a Map to hold `mail_id` and their corresponding `id` values 
    Map<Long, Long> mailIdMap = new TreeMap<Long, Long>();
    for (MailidInvitation a : invitationList) {
        // mail_id, id (id is null for now)
        mailIdMap.put(a.getId(), null);
    }

    // build an SQL statement to retrieve any existing values
    StringBuilder sb = new StringBuilder(
            "SELECT id, mail_id " +
            "FROM mail_contacts " +
            "WHERE mail_id IN (");
    int n = 0;
    for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
        if (n++ > 0) sb.append(',');
        sb.append(entry.getKey());
    }
    sb.append(')');
    String sql = sb.toString();

    // run the query and save the results (if any) to the Map
    try (Statement s = dbConn.createStatement()) {
        // <demo>
        System.out.println(sql);
        // </demo>
        try (ResultSet rs = s.executeQuery(sql)) {
            while (rs.next()) {
                mailIdMap.put(rs.getLong("mail_id"), rs.getLong("id"));
            }
        }
    }

    // <demo>
    System.out.println();
    System.out.println("mailIdMap now contains:");
    // </demo>

    // build a list of the `mail_id` values to INSERT (where id == null)
    //     ... and print the existing mailIdMap values for demo purposes
    List<Long> mailIdsToInsert = new ArrayList<Long>();
    for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
        String idValue = "";  // <demo />
        if (entry.getValue() == null) {
            mailIdsToInsert.add(entry.getKey());
            // <demo>
            idValue = "null";  
        } else {
            idValue = entry.getValue().toString();
            // </demo>
        }
        // <demo>
        System.out.println(String.format(
                "    %d - %s", 
                entry.getKey(),
                idValue));
        // </demo>
    }

    // batch insert `mail_id` values that don't already exist
    try (PreparedStatement ps = dbConn.prepareStatement(
            "INSERT INTO mail_contacts (mail_id) VALUES (?)", 
            PreparedStatement.RETURN_GENERATED_KEYS)) {
        for (Long mid : mailIdsToInsert) {
            ps.setLong(1, mid);
            ps.addBatch();
        }
        ps.executeBatch();
        // get generated keys and insert them into the Map
        try (ResultSet rs = ps.getGeneratedKeys()) {
            n = 0;
            while (rs.next()) {
                mailIdMap.put(mailIdsToInsert.get(n++), rs.getLong(1));
            }
        }
    }

    // <demo>
    System.out.println();
    System.out.println("After INSERT INTO mail_contacts, mailIdMap now contains:");
    for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
        System.out.println(String.format(
                "    %d - %s", 
                entry.getKey(),
                entry.getValue()));
    }
    // </demo>

    // now insert the `inv_table` rows
    try (PreparedStatement ps = dbConn.prepareStatement(
            "INSERT INTO inv_table (mid, aid) VALUES (?,?)")) {
        ps.setLong(2, aid);
        for (MailidInvitation a : invitationList) {
            ps.setLong(1, mailIdMap.get(a.getId()));
            ps.addBatch();
        }
        ps.executeBatch();
    }
    dbConn.commit();
}

परिणामी कंसोल आउटपुट इस तरह दिखता है:

SELECT id, mail_id FROM mail_contacts WHERE mail_id IN (11,12,13)

mailIdMap now contains:
    11 - null
    12 - 1
    13 - null

After INSERT INTO mail_contacts, mailIdMap now contains:
    11 - 15
    12 - 1
    13 - 16

कुछ JDBC ड्राइवर बैच को जारी रखने की अनुमति देते हैं यदि बैच में एक या अधिक कथन विफल हो जाते हैं। उदाहरण के लिए, MySQL Connector/J में विकल्प है continueBatchOnError जो true है डिफ़ॉल्ट रूप से। उन मामलों में एक वैकल्पिक तरीका यह होगा कि सभी mail_id . को आजमाएं और INSERT करें मान और बैच द्वारा लौटाए गए अद्यतनों की संख्या की जाँच करें। सफल INSERTs 1 की UpdateCount लौटाएंगे, जबकि INSERT जो मौजूदा mail_id के कारण विफल हो जाते हैं EXECUTE_FAILED लौटाएगा (-3)। तब हम (नया) id . प्राप्त कर सकते थे .getGeneratedKeys() . के माध्यम से सफल INSERTs के लिए मान , और फिर वापस जाने और id . को पुनः प्राप्त करने के लिए एक SELECT स्टेटमेंट बनाने के लिए आगे बढ़ें mail_id . के लिए मान प्रविष्टियाँ जो पहले से मौजूद थीं।

तो इस तरह कोड करें

// create a Map to hold `mail_id` and their corresponding `id` values 
Map<Long, Long> mailIdMap = new TreeMap<Long, Long>();
for (MailidInvitation a : invitationList) {
    // mail_id, id (id is null for now)
    mailIdMap.put(a.getId(), null);
}

// try INSERTing all `mail_id` values
try (PreparedStatement ps = dbConn.prepareStatement(
        "INSERT INTO mail_contacts (mail_id) VALUES (?)", 
        PreparedStatement.RETURN_GENERATED_KEYS)) {
    for (Long mid : mailIdMap.keySet()) {
        ps.setLong(1, mid);
        ps.addBatch();
    }
    int[] updateCounts = null;
    try {
        updateCounts = ps.executeBatch();
    } catch (BatchUpdateException bue) {
        updateCounts = bue.getUpdateCounts();
    }
    // get generated keys and insert them into the Map
    try (ResultSet rs = ps.getGeneratedKeys()) {
        int i = 0;
        for (Long mid : mailIdMap.keySet()) {
            if (updateCounts[i++] == 1) {
                rs.next();
                mailIdMap.put(mid, rs.getLong(1));
            }
        }
    }
}

// <demo>
System.out.println("mailIdMap now contains:");
// </demo>

// build a SELECT statement to get the `id` values for `mail_id`s that already existed
//     ... and print the existing mailIdMap values for demo purposes
StringBuilder sb = new StringBuilder(
        "SELECT id, mail_id " +
        "FROM mail_contacts " +
        "WHERE mail_id IN (");
int n = 0;
for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
    String idValue = "";  // <demo />
    if (entry.getValue() == null) {
        if (n++ > 0) sb.append(',');
        sb.append(entry.getKey());
        // <demo>
        idValue = "null";  
    } else {
        idValue = entry.getValue().toString();
        // </demo>
    }
    // <demo>
    System.out.println(String.format(
            "    %d - %s", 
            entry.getKey(),
            idValue));
    // </demo>
}
sb.append(')');
String sql = sb.toString();

// <demo>
System.out.println();
System.out.println(sql);
// </demo>

इस तरह कंसोल आउटपुट उत्पन्न करेगा:

mailIdMap now contains:
    11 - 17
    12 - null
    13 - 19

SELECT id, mail_id FROM mail_contacts WHERE mail_id IN (12)

बाकी प्रक्रिया पहले जैसी ही रहेगी:

  • शेष mailIdMap भरें प्रविष्टियां, और
  • INSERTs को id . का उपयोग करके दूसरी टेबल पर प्रोसेस करें mailIdMap में मान ।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. क्या मैं MySQL में मूल्य को दशमलव या पूर्णांक के रूप में संग्रहीत कर सकता हूं?

  2. रैखिक प्रतिगमन, MySQL में ढलान ढूँढना

  3. MySQL में अस्थायी प्रक्रियाएं कैसे बनाएं?

  4. एक तालिका में एक से अधिक फ़ील्ड को किसी अन्य तालिका में दर्ज करने के लिए कई को मैप करने की रणनीति

  5. जावा रेडीस्टेडमेंट निष्पादन पर SQL सिंटैक्स के बारे में शिकायत करता है ()