Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Thêm hàng vào bảng với cột duy nhất:Nhận các giá trị ID hiện có cộng với các giá trị mới được tạo

Cách tiếp cận đầu tiên này không đưa ra giả định nào về hành vi của trình điều khiển JDBC khi xử lý các INSERT hàng loạt. Nó tránh các lỗi CHÈN tiềm ẩn bởi

  • truy vấn bảng cho bất kỳ mail_id hiện có nào giá trị trong tập dữ liệu hiện tại của chúng tôi,
  • ghi chú id tương ứng giá trị cho những mail_id đó các giá trị tồn tại,
  • CHÈN mail_id các giá trị không tồn tại và truy xuất id (mới) của chúng giá trị và sau đó
  • chèn các hàng trong bảng khác (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();
}

Kết quả đầu ra của bảng điều khiển trông giống như sau:

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

Một số trình điều khiển JDBC cho phép Batch tiếp tục nếu một hoặc nhiều câu lệnh trong Batch không thành công. Ví dụ:trong MySQL Connector / J, tùy chọn là continueBatchOnError cái nào là true theo mặc định. Trong những trường hợp đó, một phương pháp thay thế sẽ là thử và CHÈN tất cả mail_id và kiểm tra số lượng cập nhật được trả về bởi Batch. INSERT thành công sẽ trả về UpdateCount là 1, trong khi INSERT không thành công do mail_id hiện có sẽ trả về EXECUTE_FAILED (-3). Sau đó, chúng tôi có thể truy xuất id (mới) giá trị cho các INSERT thành công qua .getGeneratedKeys() , và sau đó tiến hành xây dựng một câu lệnh SELECT để quay lại và truy xuất id giá trị cho mail_id các mục đã tồn tại.

Vì vậy, mã như thế này

// 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>

sẽ tạo ra đầu ra bảng điều khiển như thế này:

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

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

Phần còn lại của quy trình sẽ giống như trước:

  • điền vào mailIdMap còn lại các mục nhập và
  • xử lý các INSERT trên bảng khác bằng cách sử dụng id các giá trị trong 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. Laravel Sail xây dựng lại cơ sở dữ liệu mặc định

  2. Sử dụng Python, chèn nhanh nhiều cột vào Sqlite \ Mysql

  3. PDO Multi-query SQLSTATE [HY000]:Lỗi chung

  4. Sao lưu cơ sở dữ liệu MySQL với CodeIgniter

  5. Chọn các hàng từ bảng MySQL có dấu thời gian PHP cũ hơn X