How to check if element exists in database and return a warning message?

落爺英雄遲暮 提交于 2021-02-10 19:52:26

问题


I have a case where I am importing a spreadsheet of items, and when inserting I need to check for each item if already exists (either by serial_no or serial_imei) and then for each that EXISTS I need to inform the user when the submission is done with a message such as: "Item with serial no 123456 was already found in database".

Here is the way I am inserting:

  $stmt = $db->prepare("INSERT INTO devices (serial_imei,serial_no) VALUES (?,?)");
    for ($i = 0; $i < $min; $i++) {
        $stmt->bind_param("ii", $imei[$keysTwo[$i]], $serial_no[$keysOne[$i]]);
        $stmt->execute();
    }

I saw somewhere that I can use INSERT IGNORE but how can I do that inside loop and return a warning message for each item that has been found?


回答1:


Assuming that you have a composite UNIQUE key on both serial_imei and serial_no you can catch the exception, check if the MySQL error code is 1062 (duplicate entry) and collect this rows into a table. You can then display the table to the user to inform which ones were already existing.

Let me show you this with an example of the following code:

$imei = [1111, 2222];
$serial_no = [3333, 4444];
$min = 2;

// We will collect all duplicate keys to be displayed later
$duplicates = [];

$stmt = $mysqli->prepare("INSERT INTO devices (serial_imei,serial_no) VALUES (?,?)");
for ($i = 0; $i < $min; $i++) {
    $stmt->bind_param('ss', $imei[$i], $serial_no[$i]);
    
    // execute() is wrapped in try-catch to catch the exception from MySQL
    try {
        $stmt->execute();
    } catch (\mysqli_sql_exception $e) {
        // We are only interested in 1062 (duplicate entry) and we want to rethrow anything else
        if ($e->getCode() !== 1062) {
            // If not 1062 then rethrow
            throw $e;
        }

        $duplicates[] = ['imei' => $imei[$i], 'no' => $serial_no[$i]];
    }
}

foreach ($duplicates as $dup) {
    echo "Duplicate! IMEI:{$dup['imei']} Serial No.:{$dup['no']} ".PHP_EOL;
}

If for some reason the columns do not have UNIQUE constraint then you need to execute a parallel SELECT statement to see if the row exists prior to inserting it. This is slightly more complicated and probably also slower. If you do this, then you must first acquire a lock on the table to make sure no other process inserts duplicate rows at the same time.

$duplicates = [];

$mysqli->autocommit(0);
$mysqli->query('LOCK TABLES devices WRITE');

// SELECT stmt
$select_stmt = $mysqli->prepare("SELECT COUNT(1) FROM devices WHERE serial_imei=? AND serial_no=?");
// INSERT stmt
$stmt = $mysqli->prepare("INSERT INTO devices (serial_imei,serial_no) VALUES (?,?)");

for ($i = 0; $i < $min; $i++) {
    // First execute SELECT to check if the value exists already
    $select_stmt->bind_param('ss', $imei[$i], $serial_no[$i]);
    $select_stmt->execute();
    $exists = $select_stmt->get_result()->fetch_row()[0];
    if ($exists) {
        $duplicates[] = ['imei' => $imei[$i], 'no' => $serial_no[$i]];
    } else {
        // No result was found in DB, let's insert
        $stmt->bind_param('ss', $imei[$i], $serial_no[$i]);
        $stmt->execute();
    }
}

$mysqli->autocommit(1);
$mysqli->query('UNLOCK TABLES');


来源:https://stackoverflow.com/questions/62941220/how-to-check-if-element-exists-in-database-and-return-a-warning-message

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!