PHP 中使用 mysqli 扩展对数据库字段进行按位查询的方法,简单来说就是利用位运算(如按位与 &、按位或 | 等)来筛选符合条件的数据。
一、按位查询的核心逻辑
按位查询通常用于存储 “状态集合” 的字段(比如用数字 1 代表 “已支付”、2 代表 “已发货”、4 代表 “已签收”,字段值 3 即 1|2 代表 “已支付 + 已发货”)。核心是通过 & 运算判断目标位是否被置为 1:
语法:字段 & 目标值 = 目标值 → 表示字段包含该目标状态。
二、PHP mysqli 实现按位查询的完整示例
以下是完整的可运行代码,包含查询单状态、查询多状态、排除状态三种常见场景:
// 1. 数据库连接配置
$host = 'localhost';
$user = 'root';
$password = '你的数据库密码';
$dbname = 'test';
// 2. 建立mysqli连接(面向对象方式)
$mysqli = new mysqli($host, $user, $password, $dbname);
// 检查连接错误
if ($mysqli->connect_error) {
die('连接失败: ' . $mysqli->connect_error);
}
// 3. 按位查询示例(假设表名为order,状态字段为status)
// 状态定义:1=已支付, 2=已发货, 4=已签收, 8=已评价
$status_paid = 1; // 已支付
$status_shipped = 2; // 已发货
$status_signed = 4; // 已签收
// ========== 场景1:查询“已支付”的订单(只要包含已支付即可) ==========
echo "=== 已支付的订单 ===
";
// SQL核心:status & 1 = 1 表示包含“已支付”位
$sql1 = "SELECT * FROM `order` WHERE `status` & ? = ?";
$stmt1 = $mysqli->prepare($sql1);
// 绑定参数(两个int类型)
$stmt1->bind_param('ii', $status_paid, $status_paid);
$stmt1->execute();
$result1 = $stmt1->get_result();
while ($row = $result1->fetch_assoc()) {
echo "订单ID: {$row['id']}, 状态值: {$row['status']}
";
}
$stmt1->close();
// ========== 场景2:查询“已支付且已发货”的订单 ==========
echo "
=== 已支付且已发货的订单 ===
";
$target = $status_paid | $status_shipped; // 目标值:3
// SQL核心:(status & 3) = 3 表示同时包含已支付+已发货
$sql2 = "SELECT * FROM `order` WHERE (`status` & ?) = ?";
$stmt2 = $mysqli->prepare($sql2);
$stmt2->bind_param('ii', $target, $target);
$stmt2->execute();
$result2 = $stmt2->get_result();
while ($row = $result2->fetch_assoc()) {
echo "订单ID: {$row['id']}, 状态值: {$row['status']}
";
}
$stmt2->close();
// ========== 场景3:查询“未签收”的订单(排除已签收) ==========
echo "
=== 未签收的订单 ===
";
$sql3 = "SELECT * FROM `order` WHERE (`status` & ?) = 0";
$stmt3 = $mysqli->prepare($sql3);
$stmt3->bind_param('i', $status_signed);
$stmt3->execute();
$result3 = $stmt3->get_result();
while ($row = $result3->fetch_assoc()) {
echo "订单ID: {$row['id']}, 状态值: {$row['status']}
";
}
$stmt3->close();
// 关闭连接
$mysqli->close();
三、关键代码解释
连接数据库:使用 mysqli 面向对象方式连接,包含错误处理,避免连接失败导致代码崩溃。
预处理语句:使用 prepare() + bind_param() 绑定参数,防止 SQL 注入,这是 mysqli 的最佳实践。
按位查询核心 SQL:
status & 1 = 1:判断 status 字段是否包含 “已支付”(第 0 位为 1);
(status & 3) = 3:判断是否同时包含 “已支付 + 已发货”(第 0 位和第 1 位都为 1);
(status & 4) = 0:判断是否不包含 “已签收”(第 2 位为 0)。
结果获取:通过 get_result() 获取查询结果集,再用 fetch_assoc() 遍历数据。
四、前置条件
数据库中需有对应的表(如示例中的 order 表),且包含 status 字段(建议为 INT 类型);
PHP 环境已启用 mysqli 扩展(默认开启,可通过 phpinfo() 检查);
状态值需按 2 的幂次定义(1、2、4、8、16...),避免位冲突。
总结
按位查询的核心是利用 & 运算判断字段的指定位是否为 1,适用于 “多状态集合” 字段;
PHP mysqli 实现时,优先使用预处理语句(prepare/bind_param),避免 SQL 注入;
常见场景:单状态查询(& 目标值 = 目标值)、多状态同时满足(& 组合值 = 组合值)、排除状态(& 目标值 = 0)。