如何使用PDO查询Microsoft Access数据库的所有数据表
报错原因
Microsoft Access 的 Jet/ACE 数据库引擎不支持 MySQL 风格的 SHOW TABLES 语法,你使用的 ODBC 驱动仅支持 Access 原生规定的 DELETE/INSERT/PROCEDURE/SELECT/UPDATE 类语句,直接执行SHOW TABLES必然触发语法错误。
正确实现方式
有两种可行方案,优先推荐第一种,不需要修改Access文件权限:
方案1:调用ODBC原生表查询接口(推荐)
PDO ODBC 驱动内置了特殊的查询关键字,不需要写标准SQL就能直接调用ODBC层的表枚举能力,自动规避系统表权限问题,代码如下:
$tdb = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb, *.accdb)}; DBQ=$sdltdbsavedfilename; Uid=; Pwd=;"); $tables = []; // 传入特殊关键字tables,调用ODBC原生SQLTables接口 $tdbresult = $tdb->query("tables"); while ($row = $tdbresult->fetch(PDO::FETCH_ASSOC)) { // 仅筛选用户创建的普通表,过滤系统表、视图、存储过程 if ($row['TABLE_TYPE'] === 'TABLE') { $tables[] = $row['TABLE_NAME']; } } var_dump($tables);
方案2:查询Access隐藏系统表
Access库内自带隐藏系统表MSysObjects,存储了全库所有对象的元数据,筛选普通用户表的对应字段即可拿到表名:
$tdb = new PDO("odbc:DRIVER={Microsoft Access Driver (*.mdb, *.accdb)}; DBQ=$sdltdbsavedfilename; Uid=; Pwd=;"); // Type=1 代表表对象,Flags=0 代表用户创建的普通表,排除系统表、临时表 $sql = "SELECT Name FROM MSysObjects WHERE Type=1 AND Flags=0 ORDER BY Name"; $tdbresult = $tdb->query($sql); $tables = $tdbresult->fetchAll(PDO::FETCH_COLUMN); var_dump($tables);
如果执行上述代码报MSysObjects权限错误,需要手动打开目标Access文件,在「选项-当前数据库-导航选项」里勾选显示系统对象,再给Admin用户分配MSysObjects表的读取权限,操作比较繁琐,非必要不选这个方案。
注意事项
- Access SQL语法和其他常见数据库有差异,不要直接套用MySQL、PostgreSQL的元数据查询语句
- 方案1返回的结果会自动适配不同版本的Access驱动,不需要考虑.mdb和.accdb的格式差异
- 如果需要同时查询视图,把方案1里的判断条件改成
in_array($row['TABLE_TYPE'], ['TABLE', 'VIEW'])即可
内容的提问来源于stack exchange,提问作者Loek van Kooten
相关产品推荐
相关产品推荐

