Добавление записей в таблицы базы данных с помощью PHP

Раздел: Базы данных -> Работа с базами данных SQL в PHP

INSERT в PHP: способы вставки данных в базу

Оператор INSERT используется для добавления новых записей в таблицу базы данных. При работе с PHP важно выбирать безопасные и эффективные методы, чтобы избежать SQL-инъекций и обеспечить читаемость кода. Рассмотрим основной подход и альтернативные варианты.

Как выполнить INSERT с максимальной безопасностью и производительностью?

Наиболее эффективное решение - использование подготовленных запросов (prepared statements) через расширение PDO. Этот подход отделяет SQL-шаблон от данных, автоматически экранируя значения и предотвращая инъекции. Пример:


// Подключение к базе данных
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8mb4';
$user = 'root';
$pass = '';
$pdo = new PDO($dsn, $user, $pass);

// Подготовка запроса
$sql = 'INSERT INTO users (name, email, age) VALUES (:name, :email, :age)';
$stmt = $pdo->prepare($sql);

// Привязка параметров и выполнение
$stmt->execute([
    ':name' => 'Иван Иванов',
    ':email' => 'ivan@example.com',
    ':age' => 30
]);

echo 'Запись добавлена, ID: ' . $pdo->lastInsertId();

Php sql insert (insert в php)

Пояснение:

  • PDO поддерживает именованные плейсхолдеры (:name) или позиционные (?).
  • Метод execute() принимает массив значений, которые автоматически экранируются.
  • lastInsertId() возвращает автоинкрементный ID последней вставленной записи.

Типичные ошибки и их решение

  • Ошибка синтаксиса SQL: проверьте правильность названий таблиц и столбцов, используйте одинарные кавычки для строковых значений в SQL (но в подготовленных запросах это делает PDO).
  • Дубликат первичного ключа: если столбец имеет уникальный индекс, при вставке существующего значения возникнет исключение. Используйте INSERT IGNORE или ON DUPLICATE KEY UPDATE.
  • Проблемы с кодировкой: всегда указывайте charset в DSN (utf8mb4) и устанавливайте PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4".
  • Неверные типы данных: PDO не проверяет типы, но при несоответствии MySQL может выдать ошибку. Убедитесь, что передаваемые значения соответствуют типам столбцов.

Как вставить данные через MySQLi с подготовленными запросами?

Альтернативой PDO является MySQLi, которое также поддерживает prepared statements. Пример:


$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) die('Connect Error: ' . $mysqli->connect_error);

$stmt = $mysqli->prepare('INSERT INTO users (name, email, age) VALUES (?, ?, ?)');
$stmt->bind_param('ssi', $name, $email, $age); // s - string, i - integer

$name = 'Петр Петров';
$email = 'petr@example.com';
$age = 25;
$stmt->execute();

echo 'Вставлено, ID: ' . $stmt->insert_id;
$stmt->close();
$mysqli->close();

Sql where php (условие where в sql-запросах php)

Здесь bind_param задаёт типы параметров. Этот метод более многословен, чем PDO, но также безопасен.

Как выполнить INSERT без подготовки (не рекомендуется)?

Простая конкатенация строк с данными - опасный способ, приводящий к SQL-инъекциям. Применять его стоит только в учебных целях или при абсолютной уверенности в безопасности входных данных (например, если данные приходят из доверенного источника). Пример:


$name = mysqli_real_escape_string($mysqli, $_POST['name']);
$sql = "INSERT INTO users (name) VALUES ('$name')";
$mysqli->query($sql);

Sql инъекция php (sql-инъекции в php)

Проблема:

Если забыть экранирование, злоумышленник может внедрить произвольный SQL. Всегда используйте prepared statements.

Как вставить несколько строк одним запросом?

Для массовой вставки используйте синтаксис INSERT INTO ... VALUES (...), (...), .... Пример:


$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$users = [
    ['name' => 'Анна', 'email' => 'anna@test.com'],
    ['name' => 'Борис', 'email' => 'boris@test.com']
];
foreach ($users as $user) {
    $stmt->execute($user);
}

Sql php id (использование id в sql-запросах php)

Можно также подготовить один запрос с несколькими наборами значений, но это сложнее. В PDO для массовой вставки часто используют транзакции (см. examples_adv).

Как получить ID вставленной записи в разных случаях?

После успешного INSERT можно получить автоинкрементный ID. В PDO - $pdo->lastInsertId(), в MySQLi - $stmt->insert_id или $mysqli->insert_id. Важно вызывать этот метод сразу после выполнения запроса, до других запросов.

Что делать при необходимости вставить данные из другой таблицы?

Используйте INSERT ... SELECT. Пример:


$sql = 'INSERT INTO logs (user_id, action, created_at) SELECT id, :action, NOW() FROM users WHERE email = :email';
$stmt = $pdo->prepare($sql);
$stmt->execute([':action' => 'login', ':email' => 'ivan@example.com']);

Такой запрос не требует выборки данных в PHP и выполняется эффективно.

Часто возникающие проблемы при INSERT

  • SQL-инъекция: всегда используйте подготовленные запросы.
  • Ошибка duplicate entry: обрабатывайте через try-catch и проверяйте код ошибки (23000).
  • Превышение длины поля: убедитесь, что данные не длиннее, чем определено в схеме таблицы.
  • Отсутствие обязательных полей: вставка завершится ошибкой, если поле NOT NULL не указано.
- Php sql connect (подключение к sql в php)
- Php ms sql (работа с ms sql в php)
- Php database sql (работа с базами данных sql в php)

Расширенные примеры INSERT в PHP

Как выполнить массовую вставку тысяч записей с максимальной производительностью?

При вставке большого количества строк (например, из CSV или внешнего источника) используйте транзакции и один подготовленный запрос в цикле. Это ускоряет операцию за счет снижения накладных расходов на подтверждение каждой вставки.

Пример

// Пример: вставка 1000 случайных пользователей
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '');
$pdo->beginTransaction();
$sql = 'INSERT INTO users (name, email, age) VALUES (:name, :email, :age)';
$stmt = $pdo->prepare($sql);

for ($i = 0; $i < 1000; $i++) {
    $stmt->execute([
        ':name' => 'User ' . $i,
        ':email' => "user{$i}@example.com",
        ':age' => rand(18, 80)
    ]);
}
$pdo->commit();
echo "Вставлено 1000 записей";
Результат: Вставлено 1000 записей

Пояснение:

  • Транзакция (beginTransaction / commit) объединяет все вставки в одну атомарную операцию, что значительно быстрее, чем каждая вставка с отдельным коммитом.
  • При ошибке можно откатить все изменения (rollback).
  • Рекомендуется при вставке более 100 строк.

Как вставить запись или обновить существующую (UPSERT)?

Для реализации "вставь или обнови" используйте INSERT ... ON DUPLICATE KEY UPDATE. Этот запрос вставляет новую строку, а если уже существует запись с таким же уникальным ключом, то обновляет заданные поля.

Пример

// Предполагается, что email имеет уникальный индекс
$sql = 'INSERT INTO users (name, email, age) VALUES (:name, :email, :age)
        ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
    ':name' => 'Обновленный Иван',
    ':email' => 'ivan@example.com',
    ':age' => 31
]);
echo $stmt->rowCount(); // 1 если вставка, 2 если обновление

Важно: VALUES(name) ссылается на предлагаемое значение. Альтернативно можно использовать :name.

Как вставить данные из CSV файла, обрабатывая ошибки?

Пример загрузки CSV в базу с проверкой каждой строки и пропуском некорректных записей.

Пример

$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$handle = fopen('users.csv', 'r');
if (!$handle) die('Не удалось открыть файл');

$stmt = $pdo->prepare('INSERT INTO users (name, email, age) VALUES (:name, :email, :age)');
$rowCount = 0;
$errorCount = 0;

while (($row = fgetcsv($handle, 1000, ',')) !== FALSE) {
    $name = $row[0] ?? '';
    $email = $row[1] ?? '';
    $age = isset($row[2]) ? (int)$row[2] : null;
    if (empty($name) || empty($email)) {
        $errorCount++;
        continue;
    }
    try {
        $stmt->execute([':name' => $name, ':email' => $email, ':age' => $age]);
        $rowCount++;
    } catch (PDOException $e) {
        // Логирование ошибки
        error_log("Ошибка вставки строки: " . implode(',', $row) . " - " . $e->getMessage());
        $errorCount++;
    }
}
fclose($handle);
echo "Вставлено: $rowCount, ошибок: $errorCount";
Результат: Вставлено: 950, ошибок: 50

Как вставить NULL в поле базы данных?

Если столбец допускает NULL, передавайте в запросе значение null в PHP. Важно не путать с пустой строкой. Пример:

Пример

$sql = 'INSERT INTO users (name, email, age) VALUES (:name, :email, :age)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
    ':name' => 'Пользователь без возраста',
    ':email' => 'noage@test.com',
    ':age' => null  // явно передается null
]);

Если параметр не передавать, PDO может воспринять его как неопределенное значение и вызвать ошибку. Всегда передавайте null явно.

Как использовать INSERT IGNORE для пропуска дубликатов?

Опция INSERT IGNORE позволяет вставить только те строки, которые не вызывают ошибок дублирования по уникальным индексам. Остальные строки игнорируются без генерации исключения.

Пример

$sql = 'INSERT IGNORE INTO users (email) VALUES (:email)';
$stmt = $pdo->prepare($sql);
$emails = ['ivan@example.com', 'petr@example.com', 'ivan@example.com']; // дубль
foreach ($emails as $email) {
    $stmt->execute([':email' => $email]);
}
echo 'Вставлено строк: ' . $stmt->rowCount(); // 2 (третий дубль проигнорирован)

Обратите внимание: rowCount() возвращает количество реально вставленных строк.

INSERT в PHP - comments

En
Php sql insert (php)