Как вернуть количество строк, затронутых на нескольких вставках с Mysqli Php? - PullRequest
2 голосов
/ 04 октября 2019

У меня есть функция, которая вставляет несколько строк, используя библиотеку MySqli с подготовленными инструкциями. Вставки работают отлично, проблема в том, что метод build в $stmt->affected_rows всегда возвращает количество затронутых строк как 1.

Теперь, чтобы переместить проблему затронутых строк, я создал счетчик, который подсчитывает каждый выполненный оператор. Это решение является точным. Но мне нравится использовать встроенные методы и функции, так почему же $stmt->affected_rows всегда возвращает один, даже если я вставил несколько строк? Мой код неисправен в той или иной форме? Может быть, есть чистое решение для Sql.

Вот мой код:

try {
    $query = "INSERT INTO dryenrolltb(enroll_id,id_entity,bin_type,tara_weight,dtetime_created,enrollprint_status) VALUES(?,?,?,?,?,?)";
    $stmt = $db->prepare($query);
    $stmt->bind_param('iiidsi', $enroll,$ent,$bin,$tara,$dte_create,$enr_status);
    $result['rows']['rowerrors'] = array();
    $result['rows']['rowsaffected'] = [];
    $cnt = 0;
    foreach ($arr as $value) {
        $enroll = $value['enroll'];
        $ent = $value['entid'];
        $bin = $value['bin_t'];
        $tara = $value['tara'];
        $dte_create = $value['dtecreat'];
        $enr_status = $value['enr_status'];
        if($stmt->execute()) {
            $cnt++;
        } else {
            array_push($result['rows']['rowerrors'],$value['enroll']);
        }

    }
    if ($stmt->affected_rows > 0) {
        echo "Affectionately yours";
        array_push($result['rows']['rowsaffected'], $stmt->affected_rows);
        array_push($result['rows']['rowsaffected'], $cnt);
        return $result;
    } else {
        return false;
    }
} catch (Exception $e) {
    echo "Danger exception caught";
    return false;
}

Может кто-нибудь подсказать, почему $stmt->affected_rows всегда возвращает единицу при нескольких вставках?

1 Ответ

2 голосов
/ 04 октября 2019

Нет. Кажется, что класс операторов MySQLi не может хранить промежуточное количество затронутых строк. После того, как я подумал об этом, это имеет смысл. Позвольте мне объяснить.

Каждый раз, когда вы выполняете инструкцию, это влияет на заданное количество строк. В вашем случае у вас есть простой оператор INSERT, который будет добавлять записи по одной. Поэтому каждый раз, когда вы звоните execute(), значение affected_rows равно единице.

Запрос может быть чем-то другим. Например, INSERT INTO ... SELECT или UPDATE может повлиять на несколько строк.
Вы также можете указать INSERT INTO ... ON DUPLICATE KEY UPDATE. Если ключ существует в БД, то вы ничего не вставляете. Если значения совпадают, вы даже ничего не обновляете. Количество затронутых строк может быть 0 или более.

Причина, по которой для оператора было бы неразумно хранить промежуточную сумму затронутых строк, заключается в том, что каждое выполнение влияет на определенные строки независимо от предыдущих выполнений. Это могут быть даже одинаковые записи. Рассмотрим следующий пример:

$stmt = $mysqli->prepare('UPDATE users SET username=? WHERE id=?');
$stmt->bind_param('si', $name, $id);

$id = 102;

$name = 'Affected rows 1';
$stmt->execute();
echo $stmt->affected_rows; // 1

$name = 'Affected rows 2';
$stmt->execute();
echo $stmt->affected_rows; // 1

Оба оператора обновления обновили одну и ту же строку. Если бы mysqli оставил промежуточный итог, он бы сообщил о 2 затронутых строках, но в действительности только 1 строка была изменена. Если бы число было суммировано, вы потеряли бы информацию.

Таким образом, для вашего простого сценария хорошо держать итоги самостоятельно, например, суммируя $stmt->affected_rows после каждого выполнения. Что-нибудь еще, это, вероятно, не имеет особого смысла.

...