PHP mysql_query函数的用法与mysqli_query迁移实践指南
一、mysql_query函数概述
mysql_query是PHP早期用于执行MySQL查询的核心函数,但由于其存在严重的安全隐患和功能局限性,已在PHP 5.5.0版本中被标记为过时(deprecated),并在PHP 7.0.0版本中被完全移除。
1.1 基本语法
mixed mysql_query ( string $query [, resource $link_identifier = NULL ] )1.2 主要特点
- 仅支持同步查询
- 不支持预处理语句,容易引发SQL注入
- 错误处理机制不完善
- 不支持MySQL 4.1以上的新特性
- 仅支持单一连接
- 没有面向对象的接口
1.3 典型用法示例
<?php
// 建立连接
$link = mysql_connect('localhost', 'username', 'password');
if (!$link) {
die('连接失败: ' . mysql_error());
}
// 选择数据库
mysql_select_db('test_db', $link);
// 执行查询
$result = mysql_query('SELECT * FROM users WHERE id = 1');
// 处理结果
if ($result) {
$row = mysql_fetch_assoc($result);
echo '用户名: ' . $row['username'];
// 释放结果集
mysql_free_result($result);
} else {
die('查询失败: ' . mysql_error());
}
// 关闭连接
mysql_close($link);
?>二、mysql_query的安全隐患
2.1 SQL注入风险
由于mysql_query不支持参数化查询,直接拼接用户输入会导致严重的SQL注入漏洞。
不安全 示例:
<?php
$id = $_GET['id']; // 假设用户输入: 1' OR '1'='1
$query = "SELECT * FROM users WHERE id = '$id'";
$result = mysql_query($query); // 实际执行: SELECT * FROM users WHERE id = '1' OR '1'='1'
?>2.2 错误处理缺陷
mysql_query仅在查询失败时返回FALSE,没有提供详细的错误码和错误信息,不利于问题定位。
2.3 字符集问题
mysql_query依赖mysql_set_charset设置连接字符集,如果未正确设置,可能导致中文乱码问题。
三、mysqli_query函数介绍
mysqli_query是PHP提供的MySQLi扩展中的核心查询函数,是mysql_query的替代方案,支持面向对象和面向过程两种编程风格。
3.1 基本语法
面向过程风格:
mixed mysqli_query ( mysqli $link , string $query [, int $resultmode = MYSQLI_STORE_RESULT ] )面向对象风格:
mysqli_result mysqli::query ( string $query [, int $resultmode = MYSQLI_STORE_RESULT ] )3.2 主要特点
- 支持预处理语句(Prepared Statements)
- 支持事务处理
- 支持多语句查询
- 支持MySQL新特性
- 完善的错误处理机制
- 支持面向对象和面向过程两种接口
- 支持连接池
四、从mysql_query迁移到mysqli_query
4.1 迁移准备
- 确保PHP版本在5.5.0以上
- 确保已启用MySQLi扩展
- 备份原有代码和数据库
- 分析原有代码的数据库操作逻辑
4.2 迁移步骤
步骤1:连接数据库的迁移
原mysql_query连接方式:
$link = mysql_connect('localhost', 'username', 'password');
mysql_select_db('test_db', $link);
mysql_set_charset('utf8', $link);新mysqli_query连接方式:
面向过程:
$mysqli = mysqli_connect('localhost', 'username', 'password', 'test_db');
mysqli_set_charset($mysqli, 'utf8');面向对象:
$mysqli = new mysqli('localhost', 'username', 'password', 'test_db');
$mysqli->set_charset('utf8');步骤2:查询执行的迁移
原mysql_query查询方式:
$result = mysql_query('SELECT * FROM users WHERE id = 1');新mysqli_query查询方式:
面向过程:
$result = mysqli_query($mysqli, 'SELECT * FROM users WHERE id = 1');面向对象:
$result = $mysqli->query('SELECT * FROM users WHERE id = 1');步骤3:结果处理的迁移
原mysql_query结果处理:
if ($result) {
while ($row = mysql_fetch_assoc($result)) {
echo $row['username'] . '<br>';
}
mysql_free_result($result);
}新mysqli_query结果处理:
面向过程:
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
echo $row['username'] . '<br>';
}
mysqli_free_result($result);
}面向对象:
if ($result) {
while ($row = $result->fetch_assoc()) {
echo $row['username'] . '<br>';
}
$result->free();
}步骤4:错误处理的迁移
原mysql_query错误处理:
$result = mysql_query($query);
if (!$result) {
die('查询失败: ' . mysql_error());
}新mysqli_query错误处理:
面向过程:
$result = mysqli_query($mysqli, $query);
if (!$result) {
die('查询失败: ' . mysqli_error($mysqli) . ' (错误码: ' . mysqli_errno($mysqli) . ')');
}面向对象:
$result = $mysqli->query($query);
if (!$result) {
die('查询失败: ' . $mysqli->error . ' (错误码: ' . $mysqli->errno . ')');
}步骤5:安全查询的迁移(使用预处理语句)
原不安全的mysql_query查询:
$username = $_POST['username'];
$password = $_POST['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysql_query($query);新的mysqli预处理语句查询:
面向过程:
$stmt = mysqli_prepare($mysqli, "SELECT * FROM users WHERE username = ? AND password = ?");
mysqli_stmt_bind_param($stmt, "ss", $username, $password);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);面向对象:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();4.3 完整迁移示例对比
原mysql_query完整代码:
<?php
// 建立连接
$link = mysql_connect('localhost', 'root', '123456');
if (!$link) {
die('连接失败: ' . mysql_error());
}
// 选择数据库
mysql_select_db('test_db', $link);
mysql_set_charset('utf8', $link);
// 执行查询
$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";
$result = mysql_query($query);
// 处理结果
if ($result) {
$row = mysql_fetch_assoc($result);
echo 'ID: ' . $row['id'] . '<br>';
echo '用户名: ' . $row['username'] . '<br>';
echo '邮箱: ' . $row['email'] . '<br>';
mysql_free_result($result);
} else {
die('查询失败: ' . mysql_error());
}
// 关闭连接
mysql_close($link);
?>新mysqli_query完整代码(面向对象):
<?php
// 建立连接
$mysqli = new mysqli('localhost', 'root', '123456', 'test_db');
if ($mysqli->connect_error) {
die('连接失败: ' . $mysqli->connect_error . ' (错误码: ' . $mysqli->connect_errno . ')');
}
$mysqli->set_charset('utf8');
// 执行安全查询
$id = $_GET['id'];
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
// 处理结果
if ($result) {
$row = $result->fetch_assoc();
echo 'ID: ' . $row['id'] . '<br>';
echo '用户名: ' . $row['username'] . '<br>';
echo '邮箱: ' . $row['email'] . '<br>';
$result->free();
$stmt->close();
} else {
die('查询失败: ' . $mysqli->error . ' (错误码: ' . $mysqli->errno . ')');
}
// 关闭连接
$mysqli->close();
?>五、迁移注意事项
5.1 函数名变化
- mysql_connect → mysqli_connect 或 new mysqli
- mysql_select_db → 连接时指定数据库或mysqli_select_db
- mysql_query → mysqli_query 或 $mysqli->query
- mysql_fetch_assoc → mysqli_fetch_assoc 或 $result->fetch_assoc
- mysql_error → mysqli_error 或 $mysqli->error
- mysql_close → mysqli_close 或 $mysqli->close