章 50. 数据库问题

本节包括 PHP 和数据库之间关系的常见问题。是的,PHP 事实上可以访问如今现有的任何数据库。

1. 听说 PHP 有可能访问 Microsoft SQL Server,怎样访问?
2. 能访问 Microsoft Access 数据库吗?
3. 我升级到了 PHP 4,结果 MySQL 不断报告“Warning: MySQL: Unable to save result set in ..”,这是怎么回事?
4. PHP 5 不再绑定 MySQL 客户端库,这对我意味着什么?我还能在 PHP 中使用 MySQL 吗?我试着使用 MySQL 结果得到“function undefined”错误,怎么办?
5. 在安装共享 MySQL 支持之后,只要一加载 libphp4.so,Apache就会 core dump。这个问题能解决吗?
6. 为什么我得到类似如下的错误:“Warning: 0 is not a MySQL result index in <file> on line <x>”或者“Warning: Supplied argument is not a valid MySQL result resource in <file> on line <x>”?

1. 听说 PHP 有可能访问 Microsoft SQL Server,怎样访问?

在 Windows 机器中,可以简单地使用内置的 ODBC 支持和正确的 ODBC 驱动程序。

在 Unix 机器中,可以用 Sybase-CT 驱动程序来访问 Microsoft SQL Server,因为它们的协议是(至少大部分)兼容的。Sybase 做了一个 Linux 系统下所需库的免费版本。对于其它 Unix 操作系统,需要和 Sybase 联系来得到正确的库。同样也看看下一个问题的回答。

2. 能访问 Microsoft Access 数据库吗?

可以。如果完全在 Windows 9x/Me/NT/2000 下运行,那已经有了所有所需的工具,可以用 ODBC 和 Microsoft's ODBC drivers for Microsoft Access database。

如果在 Unix 下运行 PHP 而想访问 Windows 中的 MS Access,那需要 Unix ODBC 驱动程序。OpenLink Software 有一个基于 Unix 的 ODBC 驱动程序可以做这件事。可以下载和试用一个不会过期的免费程序,商业支持版本的价格从 $675 起。

另外一个替代方案是用带 Windows ODBC 驱动的 SQL Server 并用它来储存数据,可以通过 Microsoft Access(用 ODBC)和 PHP(用内置驱动)来访问,或者用一个 Access 和 PHP 都识别的中间文件格式,例如 flat 文件或者 dBase 数据库。关于这一点 OpenLink Software 的 Tim Hayes 写道:

当可以通过 ODBC 直接从 PHP 访问数据库时――例如用 OpenLink 的驱动程序,使用其它数据库做中间媒介不是一个好主意。如果确实需要一个中间文件格式,OpenLink 已经发布了对应于 Windows NT,Linux 和其它 Unix 平台的 Virtuoso(一个虚拟数据库引擎)。请访问我们的网站来免费下载。

还有一个已被证实有效的选择是在 Windows 下用 MySQL 和它的 MyODBC 驱动来同步数据库。Steve Lawrence 写道:

  • 根据 MySQL 的说明在你的平台上安装 MySQL。可以从 www.mysql.com 得到最新版(从离你最近的镜像站点下载!)。除了设定数据库和配置用户帐号以外不需要特殊的配置,应该在 host 字段中放一个 % 或者要用来访问 MySQL 的 Windows 机器名。记下自己的服务器名,用户名和密码。

  • 从 MySQL 网站下载 MyODBC for Windows 驱动程序。最新版是 myodbc-2_50_19-win95.zip(也可以用于 NT,以及源代码)。在你的 Windows 机器中安装它。可以用此程序中包括的工具来测试其操作。

  • 用控制面板中的 ODBC 管理器新建一个用户或系统 dsn,设定 dsn 名称,输入你在第一步中配置的 MySQL 数据库的主机名,用户名,密码,端口等。

  • 完整安装 Access,这样可以确保得到适当的插件 ... 至少需要 ODBC 支持和连接表管理器。

  • 新建一个 Access 数据库。在 Table 窗口点击右键并选择 Link Tables,或者在 File 菜单下选择 Get External Data -> Link Tables。当文件浏览窗口打开后,选择文件类型为:ODBC。接着选择 System dsn 以及在第三步建立的 dsn 的名字。再选择要连接的表,点击 OK。现在你可以在你的 MySQL 服务器中打开表并新建/删除/编辑数据了!也可以构造查询,导入/导出表到 MySQL,构造表单和报告等。

提示与技巧:

  • 可以在 Access 中构造表并导出到 MySQL 中,再把它们连接回来。这样可以使表的建立更快。

  • 在 Access 中建立表时,必需定义一个基本键名来取得表的写权限。确认在把表连接到 Access 之前在 MySQL 中建立了基本键名。

  • 如果在 MySQL 中修改了表,必须重新连接到 Access。打开 Tools>Add-ins>Linked table manager,找到你的 ODBC DSN,然后在这里选择要重新连接的表。也可以在这里移动 dsn 源,在点击 OK 之前选中 always prompt for new location。

3. 我升级到了 PHP 4,结果 MySQL 不断报告“Warning: MySQL: Unable to save result set in ..”,这是怎么回事?

看上去最有可能的是,PHP 4 在编译时使用了 --with-mysql 选项但没有指定 MySQL 的路径。这意味着 PHP 使用了它自己内置的 MySQL 客户端库。如果你的系统运行了使用其它版本的 MySQL 客户端库的应用程序,例如作为 Apache 模块的 PHP 3,那么在两个不同版本的客户端之间有冲突。

重新编译 PHP 4,并在标记中加上 MySQL 的路径“--with-mysql=/your/path/to/mysql”通常会解决此问题。

4. PHP 5 不再绑定 MySQL 客户端库,这对我意味着什么?我还能在 PHP 中使用 MySQL 吗?我试着使用 MySQL 结果得到“function undefined”错误,怎么办?

是的。PHP 总是支持 MySQL 的,不是这种方法就是那种方法。在 PHP 5 中唯一的改变就是不再绑定客户端库本身了。部分原因是(无特定顺序):

  • 现今大多数系统已经安装了客户端库了。

  • 由于以上原因,保持多个版本的库文件会导致混乱。例如,如果把 mod_auth_mysql 连接到某个版本,但把 PHP 连接到了另一个版本,然后在 Apache 中同时激活了它们,会得到无数错误。此外,绑定的库文件也不总是能和服务器端的版本很好地配合。对此最明显的症状是上哪里去找 UNIX 域套接字文件 mysql.socket。

  • 维护有些松懈,并且已经越来越落后于发行的版本了。

  • 未来的库版本是基于 GPL 的,因此我们没有升级的途径了,因为我们不能将基于 GPL 的库和 BSD/Apache 风格许可证的项目绑定到一起。因此具有一个干净的 PHP 5 是最好的选择。

事实上这并不会影响到太多人。UNIX 用户,起码是那些知道自己在做什么的人,往往会在编译 PHP 时通过 --with-mysql=/usr 将其绑定到自己系统中的 libmyqlclient 库上。Windows 用户可以在 php.ini 中激活 php_mysql.dll 扩展库。更多细节见 MySQL 函数中的安装指南。此外,确认 libmysql.dll 在系统路径中。具体怎样做的详情,请阅读 FAQ 中的设定 Windows 系统路径。因为 libmysql.dll(以及很多其它 PHP 有关文件)存放于 PHP 目录中,可能需要将 PHP 目录加入到系统路径中。

5. 在安装共享 MySQL 支持之后,只要一加载 libphp4.so,Apache就会 core dump。这个问题能解决吗?

如果你的 MySQL 库依靠 pthreads 连接就会这样。检查是否使用了 ldd。如果有的话,下载 MySQL 源程序编译,或者从源 rpm 的 spec 文件中去掉打开 threaded client 的选项然后重新编译。以上任一建议会解决此问题。然后再加上新的 MySQL 库重新编译 PHP。

6. 为什么我得到类似如下的错误:“Warning: 0 is not a MySQL result index in <file> on line <x>”或者“Warning: Supplied argument is not a valid MySQL result resource in <file> on line <x>”?

你试图用一个值为 0 的结果资源号。0 表示你的查询由于某原因失败了,需要在提交查询之后和在使用返回结果资源号之前检查错误。正确的方法是用类似如下的代码:
<?php

$result
= mysql_query("SELECT * FROM tables_priv");
if (!
$result) {
    echo
mysql_error();
    exit;
}
?>
或者
<?php

$result
= mysql_query("SELECT * FROM tables_priv")
    or die(
"Bad query: " . mysql_error());
?>