W3docs

Полное руководство по обновлению данных в базе данных MySQL с помощью PHP

Обновление данных в базе данных — ключевая операция для веб-приложений с динамическим контентом. Пошаговое руководство с примерами на PHP.

Обновление данных — одна из четырёх базовых операций с базой данных (наряду с вставкой, выборкой и удалением строк). Любое приложение, позволяющее пользователям редактировать профиль, отмечать задачу выполненной или менять цену, опирается на неё. В этой главе показано, как безопасно выполнять запрос UPDATE из PHP — с помощью подготовленных запросов — и как проверить, сколько именно строк было изменено.

В этой главе предполагается, что у вас уже есть рабочее подключение к базе данных. В примерах используется mysqli; эквивалентная версия для PDO приведена в конце.

Синтаксис PHP MySQL UPDATE

Оператор UPDATE изменяет значения существующих строк. Его структура одинакова независимо от того, выполняете ли вы его из консоли MySQL или из PHP:

UPDATE table_name
SET column1 = value1, column2 = value2
WHERE some_column = some_value;
  • table_name — таблица, строки которой нужно изменить.
  • SET — столбцы для изменения и их новые значения. Столбцы, не указанные в этом списке, остаются нетронутыми.
  • WHERE — условие выбора строк для изменения. Этот раздел критически важен. Если его опустить, каждая строка в таблице будет обновлена.

Самая распространённая — и самая разрушительная — ошибка при работе с UPDATE — это забытый раздел WHERE. Запрос UPDATE users SET active = 0 деактивирует всех пользователей в таблице, а не только одного. Всегда дважды проверяйте условие WHERE перед выполнением обновления на реальных данных.

Обновление данных с помощью подготовленного запроса

Никогда не формируйте запрос UPDATE путём конкатенации пользовательского ввода непосредственно в строку SQL — это открывает уязвимость для SQL-инъекции. Вместо этого используйте подготовленный запрос: напишите запрос с заполнителями ?, а затем привяжите значения отдельно, чтобы база данных воспринимала их строго как данные.

<?php
// Reuse your connection — in practice: require 'db_connect.php';
$conn = mysqli_connect("localhost", "username", "password", "database_name");

if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}

$sql  = "UPDATE users SET email = ?, age = ? WHERE id = ?";
$stmt = mysqli_prepare($conn, $sql);

$email = "[email protected]";
$age   = 31;
$id    = 1;

// Type string: s = string, i = integer, d = double, b = blob.
// One letter per placeholder, in order.
mysqli_stmt_bind_param($stmt, "sii", $email, $age, $id);

if (mysqli_stmt_execute($stmt)) {
    echo "Record updated successfully";
} else {
    echo "Error updating record: " . mysqli_stmt_error($stmt);
}

mysqli_stmt_close($stmt);
mysqli_close($conn);
?>

Как это работает шаг за шагом:

  1. mysqli_prepare() отправляет шаблон запроса (с заполнителями ?) в MySQL.
  2. mysqli_stmt_bind_param() привязывает переменные PHP к этим заполнителям. Первый аргумент, "sii", объявляет тип каждого значения по порядку: строка, затем два целых числа. Количество и порядок букв должны точно совпадать с заполнителями.
  3. mysqli_stmt_execute() выполняет запрос и возвращает true в случае успеха и false в случае ошибки.

Проверка количества изменённых строк

То, что mysqli_stmt_execute() возвращает true, означает лишь, что запрос выполнился без ошибок — это не значит, что строка действительно изменилась. Если условие WHERE не соответствует ни одной строке (или новые значения идентичны старым), ни одна строка не будет затронута. Используйте mysqli_stmt_affected_rows(), чтобы это выяснить:

<?php
$conn = mysqli_connect("localhost", "username", "password", "database_name");

$sql  = "UPDATE users SET age = ? WHERE id = ?";
$stmt = mysqli_prepare($conn, $sql);

$age = 40;
$id  = 1;
mysqli_stmt_bind_param($stmt, "ii", $age, $id);
mysqli_stmt_execute($stmt);

$rows = mysqli_stmt_affected_rows($stmt);
if ($rows > 0) {
    echo "Updated {$rows} row(s).";
} else {
    echo "No row matched, or the value was already up to date.";
}

mysqli_stmt_close($stmt);
mysqli_close($conn);
?>

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

Обновление данных с помощью PDO

PDO — более переносимая альтернатива mysqli: один и тот же код работает с MySQL, PostgreSQL, SQLite и другими СУБД, а именованные заполнители делают длинные запросы удобнее для чтения:

<?php
$pdo = new PDO(
    "mysql:host=localhost;dbname=database_name;charset=utf8mb4",
    "username",
    "password",
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);

$stmt = $pdo->prepare(
    "UPDATE users SET email = :email, age = :age WHERE id = :id"
);

$stmt->execute([
    ':email' => '[email protected]',
    ':age'   => 31,
    ':id'    => 1,
]);

echo "Updated " . $stmt->rowCount() . " row(s).";
?>

При установленном PDO::ERRMODE_EXCEPTION неудавшийся запрос выбрасывает исключение, которое можно перехватить, вместо того чтобы молча завершиться неудачей. rowCount() — это аналог mysqli_stmt_affected_rows() в PDO.

Рекомендации

  • Всегда включайте раздел WHERE, если вы действительно не собираетесь обновлять каждую строку.
  • Используйте подготовленные запросы для любых значений, поступающих от пользователя — никогда не используйте конкатенацию строк.
  • Соответствие строки типов привязки ("sii" и т. д.) фактическим типам переменных позволяет избежать неявных преобразований.
  • Оборачивайте обновления нескольких таблиц в транзакцию, чтобы они либо все завершались успешно, либо все откатывались.
  • Создавайте резервную копию важных данных перед выполнением масштабных или разовых обновлений в production-среде.

Практика

Практика
Что важно учитывать при обновлении данных с помощью PHP в MySQL?
Что важно учитывать при обновлении данных с помощью PHP в MySQL?
Was this page helpful?