← PHP创建MySQL表的三种方式:告别mysql_query PHP更新MySQL数据记录:从基础到实践 →

PHP插入数据库记录:告别mysql_query正确使用mysqli与PDO

原创 2026-05-21 PHP 已有人查阅

和创建表一样,往数据库里插入数据(INSERT)也是PHP开发中的高频操作。在PHP 5.5之前,很多老程序员用mysql_query()一条一条往里塞数据。但这个函数早已被官方废弃,主要原因还是安全风险功能缺失

你现在需要掌握的两种替代方案:

  • mysqli_query() — 配合MySQLi扩展使用

  • PDO::exec() / PDO::prepare() — 配合PDO扩展使用

这篇文章不讲废话,直接以插入记录为实战目标,带你把这几种写法吃透。顺便也会聊一下为什么你该尽早放弃老思路。

1. 插入记录的核心SQL语句:INSERT INTO

不管用什么PHP扩展,最终执行的SQL核心不变:

INSERT INTO 表名 (列1, 列2, 列3) VALUES (值1, 值2, 值3)

专业名词提醒

  • INSERT:数据操作语言(DML)的一种

  • VALUES:指定要插入的具体数据

  • 字符串必须用引号:在SQL中,字符串类型的值要用单引号或双引号包起来

2. 方法一:MySQLi 面向过程写法

这种方式最直白。适合小型脚本或刚刚接触PHP数据库操作的新手。

代码号示例:向员工表插入一条记录

<?php  
$host = 'localhost:3306';  
$user = 'code_user';          // 生产环境请不要用root
$pass = 'SafePass2026';  
$dbname = 'company_db';  

// 建立连接
$conn = mysqli_connect($host, $user, $pass, $dbname);  

if(!$conn){  
    die('连接失败:' . mysqli_connect_error());  
}  

// 插入一条记录(name 和 salary)
$sql = "INSERT INTO emp_basic (name, salary) VALUES ('李明', 7500)";  

if(mysqli_query($conn, $sql)){  
    echo "记录插入成功,新插入的ID为:" . mysqli_insert_id($conn);  
} else {  
    echo "插入失败:" . mysqli_error($conn);  
}  

mysqli_close($conn);  
?>  

个人经验分享

很多人只用mysqli_query()返回true/false就结束了,但其实有一个函数非常实用:mysqli_insert_id()。如果你的表有AUTO_INCREMENT主键(比如id列),这个函数会返回刚插入那行数据生成的自增ID。尤其是在后面要做关联插入(比如用户注册后立刻要往其他表写用户ID)时,这个值必不可少。

为什么早期老代码喜欢用mysql_query插数据?
因为写起来够短。但它不带预处理机制,SQL注入风险极大。上面的示例里,如果$_POST['name']直接拼进SQL,恶意用户就可以通过特殊构造的参数破坏你的数据库。

3. 方法二:MySQLi 面向对象写法

相比面向过程,这种写法结构更清晰。可读性更好,适合中大型项目。

代码号示例:使用面向对象的MySQLi插入更多字段

<?php  
$servername = "localhost";  
$username = "code_user";  
$password = "SafePass2026";  
$dbname = "company_db";  

$conn = new mysqli($servername, $username, $password, $dbname);  

if ($conn->connect_error) {  
    die("连接失败:" . $conn->connect_error);  
}  

// 插入更完整的用户资料
$sql = "INSERT INTO users_profile (fullname, email) VALUES ('王芳', 'wang@ebingou.cn')";  

if ($conn->query($sql) === TRUE) {  
    echo "新记录插入成功,ID:" . $conn->insert_id;  
} else {  
    echo "插入出错:" . $conn->error;  
}  

$conn->close();  
?>  

个人见解

面向对象的方式,insert_id是一个属性,写法更统一。而且当项目逐渐变大,你需要封装数据库操作类时,面向对象的风格会更容易集成。

不过这里必须说一句:上面这两个MySQLi示例其实还有改进空间。它们都是直接把变量拼进SQL。真正的项目里,更可靠的做法是使用“预处理语句”。这算是我踩坑多次后养成的习惯。

4. 方法三:PDO 插入记录(推荐方式)

PDO是我个人在生产环境中使用频率较高的方式。它有两个关键优势:

  • 支持预处理:从根本上解决SQL注入

  • 异常机制:错误处理更清晰

代码号示例:PDO插入数据 + 异常处理

<?php  
$servername = "localhost";  
$username = "code_user";  
$password = "SafePass2026";  
$dbname = "company_db_pdo";  

try {  
    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);  
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  

    // 插入数据
    $sql = "INSERT INTO users_profile (fullname, email) VALUES ('张立', 'zhang@ebingou.cn')";  
    $conn->exec($sql);  

    // 获取之后插入的ID
    $last_id = $conn->lastInsertId();  
    echo "记录插入成功,之后插入的ID:" . $last_id;  

} catch(PDOException $e) {  
    echo "执行失败:" . $e->getMessage();  
}  

$conn = null;  
?>  

关于exec()和query()的区别

  • exec():用于INSERT、UPDATE、DELETE等不返回结果集的SQL,返回值是受影响的行数

  • query():用于SELECT等会返回结果集的SQL

5. 进阶:预处理语句(防SQL注入的关键)

前面提到的示例都是静态SQL。但在Web应用中,用户输入的数据是动态的。这时候如果直接拼SQL,就会产生严重的安全隐患。

下面以PDO预处理为例展示一个更安全的插入写法。这也是本节课程知识要点的核心内容。

// 假设用户通过表单提交了姓名和邮箱
$fullname = $_POST['fullname'];
$email    = $_POST['email'];

try {
    $conn = new PDO("mysql:host=localhost;dbname=company_db_pdo", "code_user", "SafePass2026");
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 预处理:使用占位符 :name 和 :email
    $stmt = $conn->prepare("INSERT INTO users_profile (fullname, email) VALUES (:name, :email)");
    
    // 绑定参数并执行
    $stmt->execute([
        ':name'  => $fullname,
        ':email' => $email
    ]);

    echo "用户 " . $fullname . " 注册成功";
} catch(PDOException $e) {
    echo "插入失败:" . $e->getMessage();
}

为什么我不建议在老项目中继续用mysql_query风格插入数据?

  • 不支持预处理:一旦字段值里出现单引号、SQL关键字,轻则报错,重则被拖库

  • 没有异常机制:错误信息混乱,不利于调试

  • 维护成本高:当表结构复杂、字段一多,拼SQL的代码就会变得难以阅读

6. 三种插入方式的适用场景

场景 推荐方式 理由
学习阶段、极简脚本 MySQLi面向过程 代码直观,快速上手
中小型项目 MySQLi面向对象 结构清晰,便于封装
新项目、多人协作、注重安全 PDO + 预处理 防注入、支持多数据库、异常处理完善

个人主观建议

如果你是2026年才开始学习PHP,可以直接跳过MySQLi面向过程的写法,从PDO预处理开始练。这不代表MySQLi不能用,而是从成本和收益来看,PDO的学习曲线更值得投入。大多数现在PHP框架(Laravel、ThinkPHP等)底层操作数据库用的也是PDO或基于PDO的封装。

7. 常见问题(个人踩坑记录)

  1. 插入成功但表里看不到数据:检查你是否在事务(Transaction)中执行了INSERT但没有提交(commit)。

  2. 中文显示乱码:连接数据库后立即执行$conn->exec("SET NAMES utf8")

  3. insert_id返回0:检查表中是否有AUTO_INCREMENT的主键字段。

  4. mysqli_query返回false但没有错误信息:检查连接是否还在,或者是否执行了不支持的SQL操作。

插入数据是CRUD中非常基础但高频的操作。从废弃的mysql_query()mysqli_query()再到PDO,每一次演进都更重视安全性可维护性。写代码时不光要“跑通”,更要考虑半年后别人(包括你自己)还能不能读懂和修改。希望这篇文章能帮你少走一些弯路。

← PHP创建MySQL表的三种方式:告别mysql_query PHP更新MySQL数据记录:从基础到实践 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号