Вставка записи в таблицу средствами PHP: обзор методов и практические примеры
Основные способы вставки записи в таблицу через PHP
Рекомендуемый метод: PDO с подготовленными запросами
Для вставки данных в базу данных из PHP наиболее надёжным и безопасным способом считается использование расширения PDO (PHP Data Objects) с подготовленными выражениями (prepared statements). Этот подход защищает от SQL-инъекций, упрощает работу с разными СУБД и позволяет повторно использовать один запрос с разными параметрами.
// Файл db.php (подключение к БД)
$host = 'localhost';
$dbname = 'test';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Ошибка подключения: " . $e->getMessage());
}
// Вставка записи
$sql = "INSERT INTO users (name, email, age) VALUES (:name, :email, :age)";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':name' => 'Иван',
':email' => 'ivan@example.com',
':age' => 25
]);
echo "Запись добавлена. ID: " . $pdo->lastInsertId();Function mysql php (функции mysql в php)
Пояснение: сначала создаётся объект PDO с указанием типа базы данных, хоста и имени базы. Включён режим выброса исключений при ошибках. Затем пишется SQL-запрос с именованными плейсхолдерами (:name, :email, :age). Метод prepare возвращает объект PDOStatement, который затем выполняется с массивом значений. После успешного выполнения можно получить ID только что вставленной записи через lastInsertId.
Типичные ошибки: неправильно указан DSN (источник данных), отсутствует драйвер PDO для MySQL, синтаксическая ошибка в SQL-запросе (например, пропущена запятая), попытка вставить значение недопустимого типа (строка вместо числа). Решение: проверять DSN, установить расширение php_pdo_mysql, использовать $pdo->errorInfo() для диагностики, а также явно указывать тип параметров при bindParam.
Как выполнить вставку с помощью расширения mysqli в объектно-ориентированном стиле?
Цель: работа только с MySQL без необходимости переключения на другие СУБД, более низкоуровневый контроль.
$mysqli = new mysqli('localhost', 'root', '', 'test');
if ($mysqli->connect_error) {
die("Ошибка подключения: " . $mysqli->connect_error);
}
$stmt = $mysqli->prepare("INSERT INTO users (name, email, age) VALUES (?, ?, ?)");
$stmt->bind_param('ssi', $name, $email, $age);
$name = 'Петр';
$email = 'petr@example.com';
$age = 30;
$stmt->execute();
echo "Запись добавлена. ID: " . $stmt->insert_id;
$stmt->close();
$mysqli->close();Php api mysql (api с mysql в php)
В примере используются позиционные плейсхолдеры (?) и метод bind_param, где первый аргумент - строка типов (s для строки, i для integer).
Распространённая ошибка: несоответствие количества плейсхолдеров количеству параметров в bind_param, неверный порядок типов (например, 'si' когда нужно 'is'). Решение: тщательно проверять соответствие и использовать $stmt->error для выявления ошибок.
Как сделать вставку через mysqli в процедурном стиле?
Цель: для тех, кто привык к процедурным функциям или работает с унаследованным кодом.
$link = mysqli_connect('localhost', 'root', '', 'test');
if (!$link) {
die("Ошибка подключения: " . mysqli_connect_error());
}
$stmt = mysqli_prepare($link, "INSERT INTO users (name, email, age) VALUES (?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'ssi', $name, $email, $age);
$name = 'Мария';
$email = 'maria@example.com';
$age = 28;
mysqli_stmt_execute($stmt);
echo "Запись добавлена. ID: " . mysqli_stmt_insert_id($stmt);
mysqli_stmt_close($stmt);
mysqli_close($link);Table entry php (php: вставка записи в таблицу)
Функции полностью симметричны объектно-ориентированному аналогу.
Типичная проблема: забывают закрыть подготовленный запрос и соединение, что ведёт к утечке ресурсов. Решение: всегда вызывать mysqli_stmt_close и mysqli_close после окончания работы.
Как вставить несколько записей за один раз с использованием транзакции?
Цель: массовая вставка данных с гарантией атомарности - все записи добавляются или ни одна.
try {
$pdo->beginTransaction();
$sql = "INSERT INTO logs (message, created_at) VALUES (:msg, :dt)";
$stmt = $pdo->prepare($sql);
$entries = [
['msg' => 'Пользователь вошёл', 'dt' => '2025-03-01 10:00:00'],
['msg' => 'Пользователь вышел', 'dt' => '2025-03-01 12:30:00'],
];
foreach ($entries as $entry) {
$stmt->execute([':msg' => $entry['msg'], ':dt' => $entry['dt']]);
}
$pdo->commit();
} catch (PDOException $e) {
$pdo->rollBack();
echo "Транзакция отменена: " . $e->getMessage();
}удаленная php mysql (удаленное подключение к mysql в php)
Сначала начинается транзакция, затем в цикле выполняются одинаковые подготовленные запросы с разными данными. Если любое выполнение вызывает исключение, все изменения откатываются.
Распространённая ошибка: забывают откатить транзакцию при ошибке, что блокирует таблицы. Решение: всегда использовать блок try-catch с rollBack внутри catch.
Как вставить запись и сразу получить её ID (автоинкремент)?
Цель: необходимо знать первичный ключ только что созданной строки.
// PDO
$pdo->exec("INSERT INTO pages (title) VALUES ('Новая страница')");
$id = $pdo->lastInsertId();
// mysqli ООП
$mysqli->query("INSERT INTO pages (title) VALUES ('Новая страница')");
$id = $mysqli->insert_id;
// mysqli процедурный
mysqli_query($link, "INSERT INTO pages (title) VALUES ('Новая страница')");
$id = mysqli_insert_id($link);Php mysql примеры (примеры работы с mysql в php)
Метод lastInsertId в PDO и свойство insert_id в mysqli возвращают значение из столбца с AUTO_INCREMENT, созданное последним запросом.
Можно ли использовать устаревшее расширение mysql_* для вставки?
Цель: теоретически возможно, но настоятельно не рекомендуется из-за отсутствия поддержки подготовленных запросов и уязвимости к инъекциям. Пример (демонстрация, не использовать в реальных проектах):
$link = mysql_connect('localhost', 'root', '');
mysql_select_db('test', $link);
$name = mysql_real_escape_string('Ольга');
$query = "INSERT INTO users (name) VALUES ('$name')";
$result = mysql_query($query, $link);
if (!$result) {
echo "Ошибка: " . mysql_error();
}
mysql_close($link);Такой код уязвим, если не экранировать данные вручную. Вывод: следует мигрировать на PDO или mysqli.
Основная проблема: расширение mysql_* удалено из PHP 7.0, поэтому код не будет работать на современных версиях. Решение: обновить код до PDO или mysqli.
Расширенные примеры вставки записей
Пример 1: вставка с проверкой существования записи
Перед вставкой полезно убедиться, что данные ещё не существуют, чтобы избежать дубликатов. Используется подзапрос или проверка через SELECT.
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '');
$email = 'user@example.com';
// Проверяем, есть ли пользователь с таким email
$check = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email = :email");
$check->execute([':email' => $email]);
$exists = $check->fetchColumn();
if (!$exists) {
$insert = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$insert->execute([':name' => 'Новый', ':email' => $email]);
echo "Добавлен пользователь с ID " . $pdo->lastInsertId();
} else {
echo "Пользователь с таким email уже существует.";
}Вывод: "Добавлен пользователь с ID 42" или "Пользователь с таким email уже существует."
Пример 2: пакетная вставка большого количества записей через подготовленные запросы и транзакцию
Когда нужно вставить тысячи строк, стоит использовать один подготовленный запрос и выполнять его в цикле внутри транзакции. Это значительно ускоряет операцию.
$pdo->beginTransaction();
$sql = "INSERT INTO test_table (value) VALUES (:val)";
$stmt = $pdo->prepare($sql);
for ($i = 1; $i <= 10000; $i++) {
$stmt->execute([':val' => "Значение $i"]);
}
$pdo->commit();
echo "Вставлено 10000 записей.";Вывод: "Вставлено 10000 записей." (время выполнения заметно меньше, чем при отдельных запросах)
Пример 3: вставка с использованием именованных параметров и автоматическим экранированием
PDO позволяет передавать массив с именованными плейсхолдерами. Экранирование выполняется автоматически.
$data = [
'title' => "Пользовательское соглашение",
'content' => "Текст с 'кавычками' и <тегами>",
'date' => date('Y-m-d H:i:s')
];
$sql = "INSERT INTO articles (title, content, created_at) VALUES (:title, :content, :date)";
$stmt = $pdo->prepare($sql);
$stmt->execute($data);Обратите внимание: специальные символы не нужно экранировать вручную, PDO делает это под капотом.
Пример 4: вставка бинарных данных (BLOB) через PDO
Для хранения изображений или файлов в базе данных используйте параметр с типом PDO::PARAM_LOB.
$image = file_get_contents('photo.jpg');
$sql = "INSERT INTO images (filename, data) VALUES (:filename, :data)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':filename', $filename, PDO::PARAM_STR);
$stmt->bindParam(':data', $image, PDO::PARAM_LOB);
$filename = 'photo.jpg';
$stmt->execute();
echo "Изображение сохранено.";Использование PDO::PARAM_LOB указывает, что данные могут быть большими и должны передаваться потоком.
Пример 5: вставка через хранимую процедуру
В MySQL можно заранее создать процедуру и вызывать её из PHP.
// Создание процедуры (один раз в БД)
// CREATE PROCEDURE add_user(IN p_name VARCHAR(100), IN p_email VARCHAR(100))
// BEGIN
// INSERT INTO users (name, email) VALUES (p_name, p_email);
// SELECT LAST_INSERT_ID() AS new_id;
// END
$stmt = $pdo->prepare("CALL add_user(:name, :email)");
$stmt->execute([':name' => 'Процедурный', ':email' => 'proc@example.com']);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo "Новый ID: " . $row['new_id'];Вывод: "Новый ID: 123"
Пример 6: вставка данных из CSV-файла с разбором и транзакцией
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO products (name, price) VALUES (:name, :price)");
$handle = fopen('products.csv', 'r');
fgetcsv($handle); // пропуск заголовка
while (($data = fgetcsv($handle)) !== false) {
$stmt->execute([':name' => $data[0], ':price' => (float)$data[1]]);
}
fclose($handle);
$pdo->commit();
echo "Товары из CSV добавлены.";Такой подход позволяет безопасно и быстро импортировать данные из внешних источников.