WebjxCom提示:揭露
PHP应用程序中出现的五个常见数据库问题包括数据库模式设计、数据库访问和使用数据库的业务逻辑代码以及它们的解决方案
。如果只有一种方式使用数据库是正确的您可以用很多的方式创建数据库设计、数据库访问和基于数据库的
PHP业务逻辑代码
,但最终一般以错
该代码不仅更短
,而且也更容易理解和高效
。我们不是执行两个查询,而是执行一个查询。
尽管该问题听起来有些牵强,但是在实践中我们通常总结出所有的表应该在同一个数据库中,除非有非常迫不得已的理由。
问题4:不使用关系
关系数据库不同于
编程语言,它们不具有数组类型。相反,它们使用表之间的关系来创建对象之间的一到多结构,这与数组具有相同的效果。我在应用程序中看到的一个问题是,工程师试图将数据库当作
编程语言来使用,即通过使用具有逗号分隔的标识符的文本字符串来创建数组。请看下面的模式。
DROPTABLEIFEXISTSfiles;
CREATETABLEfiles(
idMEDIUMINT,
nameTEXT,
pathTEXT
);
DROPTABLEIFEXISTSusers;
CREATETABLEusers(
idMEDIUMINT,
loginTEXT,
passwordTEXT,
filesTEXT
);
INSERTINTOfilesVALUES(1,'test1.jpg','media/test1.jpg');
INSERTINTOfilesVALUES(2,'test1.jpg','media/test1.jpg');
INSERTINTOusersVALUES(1,'jack','pass','1,2');
清单10.Bad.sql
系统中的一个用户可以具有多个文件。在编程语言中,应该使用数组来表示与一个用户相关联的文件。在本例中,程序员选择创建一个files字段,其中包含一个由逗号分隔的文件id列表。要得到一个特定用户的所有文件的列表,程序员必须首先从用户表中读取行,然后解析文件的文本,并为每个文件运行一个单独的SELECT语句。该代码如下所示。
<?php
require_once("DB.php");
functionget_files($name)
{
$dsn='
mysql://root:password@localhost/bad_norel';
$db=&DB::Connect($dsn,array());
if(PEAR::isError($db)){die($db->getMessage());}
$res=$db->query("SELECTfilesFROMusersWHERElogin=?",
array($name));
$files=null;
while($res->fetchInto($row)){$files=$row[0];}
$rows=array();
foreach(split(',',$files)as$file)
{
$res=$db->query("SELECT*FROMfilesWHEREid=?",
array($file));
while($res->fetchInto($row)){$rows[]=$row;}
}
return$rows;
}
$files=get_files('jack');
var_dump($files);
?>
清单11.Get.php
该技术很慢,难以维护,且没有很好地利用数据库。惟一的解决方案是重新架构模式,以将其转换回到传统的关系形式,如下所示。
DROPTABLEIFEXISTSfiles;
CREATETABLEfiles(
idMEDIUMINT,
user_idMEDIUMINT,
nameTEXT,
pathTEXT
);
DROPTABLEIFEXISTSusers;
CREATETABLEusers(
idMEDIUMINT,
loginTEXT,
passwordTEXT
);
INSERTINTOusersVALUES(1,'jack','pass');
INSERTINTOfilesVALUES(1,1,'test1.jpg','media/test1.jpg');
INSERTINTOfilesVALUES(2,1,'test1.jpg','media/test1.jpg');
清单12.Good.sql
这里,每个文件都通过user_id函数与文件表中的用户相关。这可能与任何将多个文件看成数组的人的思想相反。当然,数组不引用其包含的对象——事实上,反之亦然。但是在关系数据库中,工作原理就是这样的,并且查询也因此要快速且简单得多。清单13展示了相应的PHP代码。
<?php
require_once("DB.php");
functionget_files($name)
{
$dsn='
mysql://root:password@localhost/good_rel';
$db=&DB::Connect($dsn,array());
if(PEAR::isError($db)){die($db->getMessage());}
$rows=array();
$res=$db->query(
"SELECTfiles.*FROMusers,filesWHEREusers.login=?
ANDusers.id=files.user_id",
array($name));
while($res->fetchInto($row)){$rows[]=$row;}
return$rows;
}
$files=get_files('jack');
var_dump($files);
?>
清单13.Get_good.php