Skip to content

MySQL 插入数据

使用 MySQLi 和 PDO 安全地插入数据

Section titled “使用 MySQLi 和 PDO 安全地插入数据”

一旦你有了数据库和表结构,就可以在 PHP 脚本中使用 SQL INSERT INTO 语句插入数据了。确保安全性至关重要,以防范 SQL 注入漏洞。

推荐使用 预处理语句 (Prepared Statements) 结合 MySQLi 或 PDO 扩展来完成此操作。

SQL INSERT INTO 语法:

INSERT INTO table_name (column1, column2, column3, …) VALUES (value1, value2, value3, …);

构建 SQL 查询时的关键规则(尤其是不使用预处理语句时,对于用户输入,不推荐这样做):

  • 字符串值必须用单引号括起来(例如,'John Doe')。
  • 数值不应加引号(例如,42)。
  • SQL 关键字 NULL 不应加引号。
  • 日期/时间值通常作为字符串加引号(例如,'2023-10-27 10:00:00')。

**然而,依赖手动引用容易出错且不安全。**预处理语句会自动处理数据类型和转义。

示例场景:向 MyGuests 表插入数据

假设 MyGuests 表已存在(在之前的步骤中创建),包含列:id (AUTO_INCREMENT),firstname (VARCHAR),lastname (VARCHAR),email (VARCHAR),reg_date (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)。

以下示例演示了使用 MySQLi(面向对象和面向过程风格)和 PDO 插入新记录,重点在于预处理语句。

示例 1:使用预处理语句的 MySQLi(面向对象风格)

Section titled “示例 1:使用预处理语句的 MySQLi(面向对象风格)”
<?php
declare(strict_types=1);
$servername = "localhost";
$username = "your_username"; // 替换为你的数据库用户名
$password = "your_password"; // 替换为你的数据库密码
$dbname = "myDB"; // 替换为你的数据库名
// 要插入的数据(理想情况下来自已验证的源,例如表单输入)
$firstName = "John";
$lastName = "Doe";
$email = "john.doe@example.com";
// 创建连接
$conn = new mysqli($servername, $username, $password, $dbname);
// 检查连接
if ($conn->connect_error) {
// 安全地记录错误,向用户提供通用消息
error_log("Connection failed: " . $conn->connect_error);
die("Database connection error. Please try again later.");
}
// 设置字符集(推荐)
$conn->set_charset('utf8mb4');
// 准备 SQL 语句(防止 SQL 注入)
$sql = "INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)";
$stmt = $conn->prepare($sql);
if ($stmt === false) {
// 处理预处理错误
error_log("Prepare failed: (" . $conn->errno . ") " . $conn->error);
die("Error preparing database statement.");
}
// 绑定参数('sss' 表示三个字符串参数)
// 将变量绑定到占位符
$stmt->bind_param("sss", $firstName, $lastName, $email);
// 执行语句
if ($stmt->execute()) {
$last_id = $conn->insert_id; // 获取插入行的 ID
echo "New record created successfully. Last inserted ID is: " . $last_id;
} else {
// 处理执行错误
error_log("Execute failed: (" . $stmt->errno . ") " . $stmt->error);
echo "Error: Could not execute statement.";
}
// 关闭语句和连接
$stmt->close();
$conn->close();
?>

示例 2:使用预处理语句的 MySQLi(面向过程风格)

Section titled “示例 2:使用预处理语句的 MySQLi(面向过程风格)”
<?php
declare(strict_types=1);
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "myDB";
// 要插入的数据
$firstName = "Jane";
$lastName = "Roe";
$email = "jane.roe@example.com";
// 创建连接
$conn = mysqli_connect($servername, $username, $password, $dbname);
// 检查连接
if (!$conn) {
error_log("Connection failed: " . mysqli_connect_error());
die("Database connection error.");
}
// 设置字符集
mysqli_set_charset($conn, 'utf8mb4');
// 准备 SQL 语句
$sql = "INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)";
$stmt = mysqli_prepare($conn, $sql);
if (!$stmt) {
error_log("Prepare failed: (" . mysqli_errno($conn) . ") " . mysqli_error($conn));
die("Error preparing database statement.");
}
// 绑定参数
mysqli_stmt_bind_param($stmt, "sss", $firstName, $lastName, $email);
// 执行语句
if (mysqli_stmt_execute($stmt)) {
$last_id = mysqli_insert_id($conn);
echo "New record created successfully (Procedural). Last ID: " . $last_id;
} else {
error_log("Execute failed: (" . mysqli_stmt_errno($stmt) . ") " . mysqli_stmt_error($stmt));
echo "Error: Could not execute statement.";
}
// 关闭语句和连接
mysqli_stmt_close($stmt);
mysqli_close($conn);
?>
<?php
declare(strict_types=1);
$servername = "localhost";
$username = "your_username";
$password = "your_password";
$dbname = "myDBPDO"; // 假定 PDO 示例使用不同的数据库
// 要插入的数据
$firstName = "Peter";
$lastName = "Jones";
$email = "peter.jones@example.com";
try {
// 使用 PDO 创建连接
$conn = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8mb4", $username, $password);
// 设置 PDO 错误模式为异常(推荐)
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 准备 SQL 语句
$sql = "INSERT INTO MyGuests (firstname, lastname, email) VALUES (:fname, :lname, :email)";
$stmt = $conn->prepare($sql);
// 使用命名占位符绑定参数
$stmt->bindParam(':fname', $firstName);
$stmt->bindParam(':lname', $lastName);
$stmt->bindParam(':email', $email);
/* Alternatively, pass an array to execute():
$stmt->execute([
':fname' => $firstName,
':lname' => $lastName,
':email' => $email
]);
*/
// 执行语句(如果未使用 execute 方法传递数组)
$stmt->execute();
$last_id = $conn->lastInsertId(); // 获取最后插入的 ID
echo "New record created successfully (PDO). Last inserted ID is: " . $last_id;
} catch(PDOException $e) {
// 处理 PDO 错误
error_log("PDO Error: " . $e->getMessage());
echo "Database error: " . $e->getMessage(); // 在生产环境中显示通用消息
// die("Database operation failed."); // 或者优雅地终止
} catch(Exception $e) {
// 处理其他潜在错误
error_log("General Error: " . $e->getMessage());
echo "An unexpected error occurred.";
}
// 关闭连接(当脚本结束或 $conn 被销毁时,PDO 会自动关闭连接)
$conn = null;
?>

在插入源自用户或外部数据的数据时,务必始终使用预处理语句。这是防止 SQL 注入攻击最可靠的方法。

PHP 手册关于预处理语句的内容: