PHP学习笔记(八)——PHP/数据库常见问题

上一篇 / 下一篇  2007-01-17 17:35:54 / 个人分类:开发相关

1.没有连接

 

如果在PHP脚本中有数据库调用函数,但是不能打开连接。有两种可能会导致这种情况。

      第一种可能性是警告没有连接:

      Warning MySQL Connection Failed Can’t connect to MySQL server on ‘localhost’(10061) in …

      这说明问题出自MySQL服务器本身,或者出自连接mysqld的路径。在PHP自己的特殊方式中,PHP告诉它知道MYSQL,但是不能连上。

      第二种可能是问题出在PHP这方面。

      Fatal error Call to undefined function mysql_connect() in ….

      这意味着PHP根本不知道MYSQL

      在这两种错误中,解决致命错误(fatal error)要简单得多。如果遇到的未定义函数确定是PHP函数集中的函数,就可以很明确地确定只是忘了安装该模块。在UNIX中,需要用“-with-mysql”选项重新编译。在WINDOWS中,修改php.ini文件即可。

      看起来无关紧要的“No Connection”错误实际上较难诊断,因为有几个可能的原因。主要分为两类:

l        MYSQL后台程序没有运行

l        MYSQL套接字不是PHP寻找的内容

 

很容易检查mysqld是否在运行,所以可以首先进行检查。只要使用能检查出是否运行的任何方法即可。

      通常在第一次从新的服务器上启动MYSQL时出现套接字问题。虽然发生过这样的问题,但是在长期运行的站点上这种问题不是经常发生。

      通常能在php.ini文件中找到解决数据库连接问题的方法。有一部分MYSQL变量是必须仔细检查的,这些变量是在脚本中指定主机名、端口和套接字的变量。要确保没有让PHP在临时的端口或错误的默认主机上寻找MYSQL。在UNIX上,还可以检查/etc/services文件,寻找不同的套接字地址。一般情况下,应该让这些变量是公开的,除非有特殊的原因要设置它们。

 

2.权限问题

 

 

权限问题引起的错误提示信息:

 

Warning MySQL Connection Failed Access denied for user:’nohost@localshot’(Using password YES) in …

 

由于这些错误信息会引起安全性问题,最好在站点中使用静默模式,在函数mysql_connectmysql_select_db前面添加字符“@”。

      这些错误种类很多,但是主要有几种:

l        输入错误的用户名/密码

l        错误的使用要求的密码

l        试图使用不存在的密码

l        试图使用系统的用户名/密码而不是MYSQL的用户名/密码

l        使用缺少完成任务所需的权限的数据库用户名

l        使用MYSQL数据库不允许某个特定用户登录的位置或客户端登录

l        由于不正确的文件权限(必须是完全可执行目录下的完全可执行文件),PHP不能打开数据库密码包含文件

l        数据库系统故意更改权限

 

3.未转义的引号

 

引号能引起PHPMYSQL之间很小但很烦人的问题。问题的症结在于PHP在双引号内求值,很可能忽略单引号,而MYSQL在单引号内求值,很可能忽略双引号。这样必须考虑每个引号的作用。

      在大多数PHP脚本中,单引号内的变量不能被扩展,而双引号或没有引号的变量是被扩展的——所以查询看上去有些奇怪。但是如果考虑一下,会发现在两种语言中语句都是有效的。单引号存在双引号内,所以PHP把它们当作文字字符;变量实际上在双引号内,所以PHP用变量的值代替变量。可以用以下方式考虑这种分工:在数据库查询中,PHP对双引号之间的内容操作(把单引号当作文字),然后MYSQL处理留在单引号内的内容。

      这种风格的语句也消除了引起常见的PHP错误的双引号。

      更大的问题是在文本中使用单引号和双引号的字符串。在PHPMYSQL中撇好和单引号是一样的。所以如果任何姓氏有一个撇号,则SQL语句将中断。

      PHP一侧的相应问题是有双引号的字符串。这种构建方法无疑不能实现希望的功能:

      在非常长的文本条目中,引号问题将导致把部分字符串插入到数据库中,或者完全失败,或者看起来像是不允许较长的条目而允许较短的条目。

      现在介绍处理引号问题的三种方法:

l        直接在代码内使用字符串的情况下,可以用反斜杠转义必要的引号字符。

$query=”INSERT INTO employee (ID, lastname, firstname) VALUES (‘NULL’,’O\’Donnell’,’Sean’)”;

l        在用变量表示字符串的情况下,可以使用addslashes(),自动添加任何必要的反斜杠。

$string=addslashes(“He said, ‘ I’m not angry,’ but I knew he was.”)

$statement=mysql_query(“INSERT INTO diary (ID,entry) VALUES(‘NULL’,’$string’)”);

 

l        可以用-with-magic-quotes选项建立PHP,实时在php.ini文件中设置魔术引号。它将添加反斜杠,而不需要每次指定addslashes()。如果ISP控制php.ini文件,那么应该仍然能更改用户自己的.htaccess文件,设置这些变量。

 

由于一些说不清的心里原因,许多PHP用户非常不愿意使用addslashes()stripslashes()。当人们实际上不应该使用引号时,他们总是使用单引号,因此就不必转义双引号。在任何时候这样的用法都是不好的风格,尤其在使用数据库时特别危险。

当向数据库中插入值时需要添加反斜杠;相反,当从数据库中得到字符串时需要去除反斜杠(除非启用了magic-quotes选项)。

$query=”SELECT passphrase FROM userinfo WHERE username=’$username’”;

$result=mysql_query($query);

$query_row=msql_fetch_array($result);

$passphrase=stripslashes($query_row[0]);

 

      如果不能实现这项任务,那么在每次把数据重新加入到MYSQL中时添加越来越多的反斜杠。在使用重新显示从数据库中取出的值的可编辑WEB表单时,经常会遇到这样的问题。

 

4.中断的SQL语句

      除了引号问题以外,还有几个容易给数据库发送“坏”查询的方法。查询可能语法不对,或者语法正确但是引用的表不存在,或者存在什么问题使数据库不能正确地处理查询。典型的错误信息如下:

Warning Supplied argument is not a valid MYSQL result resource in …

 

      但是如果是正确的查询语句但是由于结果集中恰巧只包含0条记录。由于在其他情况下,这意味着捕获到查询失败的错误俘获程序不能帮助检测到0记录的情况。对于使用MYSQL的程序员而言,一个有助于解决这个问题的函数是mysql_num_rows(),调用它得到查询结果的ID,返回一个整数。

      一个好的示例是:

      $result_id=mysql_query($query) or die(mysql_error());

 

因为如果查询失败,mysql_query()将返回false值,所以只在失败时执行die()部分。如果赋值成功,则or的低运算优先顺序确保die()调用不会在赋值语句中起作用。一旦操作失败,只要脚本一打印出MYSQL设计者编制的信息最丰富的错误消息,就退出脚本。如果用户使用的数据库缺少PHP中的错误变量,就需要调用die($query)。通常一看到真正被发送的查询语句,错误就很明显了。

      如果没有在查询调用中设置检查错误的代码,则在后面的数据库代码中试图使用查询结果ID时将得到第一条坏消息。典型的模式是:

      $my_result=$mysql($bad_query);

      //…other processing and display code

      $row=mysql_fetch_row($my_result);  //error shows up here

 

      MySQL中典型的错误消息是“0is not a mysql result identifier in [etc.]”。这不是因为检测到在失数时mysql_query()返回的0值,而是因为用户试图使用该值,就好像它是结果集中的一个有效标识符。

      虽然糟糕的查询是产生“0 is not a valid result identifier”消息的最常见的原因,但不是唯一的原因。如果错误的拼写结果标识符变量的名称(该变量是未被设定的)或者根本没有执行查询语句,也会得到该消息。如果早些俘获错误,就更容易区分这些问题。

 

4.1拼写错误的名称

 

最常见的拼写错误包括:表、字段和值的名称拼写错误。PHPMYSQL都是区分大小写的。

 

4.2逗号引起的错误

 

SQL语句内逗号要放在单引号之外。

 

 

4.3未被引号引起来的字符串参数

 

需要在SQL语句内把应该被数据库当作字符串数据值的任何值用单引号引起来。

 

4.4未被设定的变量

中断SQL语句的一个更差的方法是在语句中插入未被设定的变量。

      由于有可能出现这种问题,所以最好构建查询语句并用单个语句把它赋给变量。然后再显式调用mysql_query()。如果这样作,就非常容易添加打印或调试语句,显示出正在发送的实际的查询。

 

 

5.数据太少或太多

      如果查询函数成功返回,但是没有显示出从数据库得到的数据,或者显示的不是预期的结果。这时则应该怀疑SQL本身。重新检查逻辑,尤其是WHERE子句。

      如果脚本正在遍历数据库记录并显示出太多的记录,则问题经常是SQL联结的约束值太少。有这样的一条约定,在WHERE子句中的约束的个数不应该低于被联结的表的数目减1

 

6.清楚的检查

      如果在调试和查询有关的错误以及不正确的结果,比较嵌入的PHP查询得到的结果与直接对数据库进行的同样查询得到的结果,可以有助于调试程序。如果安装的程序允许直接运行SQL解释器(例如,在命令行输入mysql)以及程序之间的交叉复制和粘贴,那么可以试试一下两个步骤:

l        PHP插入调试语句,在真正用于数据库查询调用语句之前立即打印查询语句本身(如print($query);)。

l        把该查询语句从浏览器输入(或HTML源文件)中直接粘贴到SQL解释器中。

 

如果查询看起来很合理,但是在SQL程序和PHP中都有问题,那么在SQL中一定存在被错过的某些语法错误或命名错误,PHP代码没有错(除非代码首先构建了该查询语句)。类似的,当数据太少或数据太多时,如果得到的结果在两个程序中都是一样的,则查询有问题。另一方面,如果在SQL解释器中结果是预期的那样,则查询语句是正确的,应该怀疑发送该查询语句以及处理结果的PHP代码有问题。

      一个常用的好技巧是非常仔细地研究任何错误消息,注意“link identifier”和“result identifier”短语。在MYSQL中,前者意味看数据库连接的标识符,后者意味着由某个查询返回的记录集的标识符。很容易混淆这两个标识符。

 

7.小结

 

PHP数据库中的bug通常不太难也不太微妙,但进行判断仍然有困难。一般情况下,越早在脚本中查到错误,就越早能诊断出问题的所在。尤其是在调试程序时,和数据库有关的每个语句应该有or die()子句,该子句包含丰富的错误消息。

到目前为止,引起数据库连接问题的最常见的原因是给连接函数提供了不正确的参数(主机名、用户名和密码)。引起查询失败的最常见的原因是引号错误、未被设定的变量和拼写错误。

      如果看起来正常的数据库查询总是失败,则打印出发送数据库的每条查询语句;如果可能,试着直接把查询用于数据库。如果问题持续到PHP结束循环时,则应该把注意力放在数据库设计以及SQL查询语句上,找出问题所在。


TAG: 开发相关

 

评分:0

我来说两句

Open Toolbar