
本文介绍如何正确使用 php 的 mysqli 扩展检索 mysql 数据库中所有以指定字符串(如 'sci-01-123')为前缀的表名,重点解决 `fetch_assoc()` 仅返回首行的问题,并提供安全、可复用的实现方案。
在开发中,有时需要动态查找符合命名模式的数据库表(例如按患者 ID 命名的系列快照表:SCI-01-123、SCI-01-123-1、SCI-01-123-2 等)。MySQL 的 SHOW TABLES LIKE 'pattern' 是理想的元数据查询方式,但配合 PHP 的 mysqli 时,常见误区是误用 fetch_assoc() —— 它每次只获取结果集的一行,因此即使查询返回多条记录,也只会输出第一个表名。
正确的做法是使用 fetch_all() 方法一次性获取全部结果。以下是推荐的完整实现:
$patient_id = 'SCI-01-123';
// ✅ 使用预处理式拼接(注意:SHOW TABLES 不支持参数化,需确保输入安全)
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $patient_id)) {
die("Invalid table prefix: contains unsafe characters");
}
$query = "SHOW TABLES LIKE '" . mysqli_real_escape_string($mysqli, $patient_id) . "%'";
$result = mysqli_query($mysqli, $query);
if (!$result) {
die("Query failed: " . mysqli_error($mysqli));
}
echo "Found " . mysqli_num_rows($result) . " matching tables:\n";
// ✅ fetch_all(MYSQLI_NUM) 返回二维数组:[[table1], [table2], ...]
$tables = mysqli_fetch_all($result, MYSQLI_NUM);
foreach ($tables as $row) {
echo $row[0] . "\n"; // 每行只有一个字段:Table_name
}
mysqli_free_result($result);? 关键说明: SHOW TABLES LIKE '...' 的结果集只有一列(列名为 Tables_in_[database]),因此 fetch_all(MYSQLI_NUM) 返回形如 [ ['SCI-01-123'], ['SCI-01-123-1'] ] 的数组,访问时用 $row[0]; 若改用 MYSQLI_ASSOC,则需 $row['Tables_in_your_db'](数据库名需替换为实际值),但 MYSQLI_NUM 更简洁通用; 虽然 SHOW TABLES 不支持原生预处理语句,仍须对 $patient_id 进行白名单校验(如正则 /^[a-zA-Z0-9_-]+$/)并配合 mysqli_real_escape_string() 防止注入; 避免直接 implode("\n", $array) —— 因 fetch_assoc() 返回的是单行关联数组(如 ['Tables_in_test' => 'SCI-01-123']),而非表名列表。
进阶建议:若需频繁执行此类操作,可封装为函数:
function findTablesByPrefix($mysqli, $prefix) {
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $prefix)) {
return [];
}
$escaped = mysqli_real_escape_string($mysqli, $prefix);
$result = mysqli_query($mysqli, "SHOW TABLES LIKE '{$escaped}%'");
return $result ? array_column(mysqli_fetch_all($result, MYSQLI_NUM), 0) : [];
}
// 使用示例
$tableNames = findTablesByPrefix($mysqli, 'SCI-01-123');
print_r($tableNames); // ['SCI-01-123', 'SCI-01-123-1']掌握 fetch_all() 的正确用法,不仅能解决当前问题,更是高效处理多行结果集的基础技能。
立即学习“PHP免费学习笔记(深入)”;











