All articles| All Pictures| All Softwares| All Video| Go home page| Write articles| Upload pictures

Reading number is top 10 articles
新手入门:IIS6环境下的PHP最佳配置方法_php资料_编程技术
Windows环境PHP打开显示空白页面_php资料_编程技术
实例:AJAX编写用户注册实例及技术小结_.net资料_编程技术
ASP.NET,2.0移动开发入门之使用模拟器_[Asp.Net教程]
初谈ADO.NET中利用DataAdapter进行数据操作_[Asp.Net教程]
SQL Server安装挂起错误解决方式_[SQL Server教程]
ASP.NET中上传并读取Excel文件数据_[Asp.Net教程]
Delphi建立字体形状窗体
ASP.NET下的一个实验MVC的小东西_[Asp.Net教程]
如何将索引碎片数量降至最低_[SQL Server教程]
Reading number is top 10 pictures
俄罗斯台球天后惊艳魅惑2
The real super beauty5
漂亮脸蛋魔鬼身材2
运动的范冰冰2
Take you to walk into the most true north Korea rural4
中国处女图鉴2
这才是真正的人体艺术2
Exquisite decoration is not paying too much4
你白吃了多少药
福利福利。。。。。。
Download software ranking
Unix video tutorial15
Boxer's Top ten classic battle10
功夫熊猫2(下集)
星际争霸1.08硬盘免安装版
传奇私服架设教程-chm
The king of fighters 97(Mobile phone games-apk)
Visual C++界面编程技术
Tram sex maniac 2 (H) rar bag4
VeryCD电驴(EasyMule) V1.1.9 Build09081
Jinling thirteen stock
归海一刀 published in(发表于) 2014/2/17 7:13:01 Edit(编辑)
5种易犯的PHP数据库错误_[PHP教程]

5种易犯的PHP数据库错误_[PHP教程]

5种易犯的PHP数据库错误_[PHP教程]

5种易犯的PHP数据库错误---包括数据库模式设计、数据库访问和使用数据库的业务逻辑代码---以及它们的解决方案。

  如果只有一种 方式使用数据库是正确的……

  您可以用很多的方式创建数据库设计、数据库访问和基于数据库的 PHP 业务逻辑代码,但最终一般以错误告终。本文说明了数据库设计和访问数据库的 PHP 代码中出现的五个常见问题,以及在遇到这些问题时如何修复它们。

  问题 1:直接使用 MySQL

  一个常见问题是较老的 PHP 代码直接使用 mysql_ 函数来访问数据库。清单 1 展示了如何直接访问数据库。

  清单 1. access/get.php

<?php
function get_user_id( $name )
{
 $db = mysql_connect( ’localhost’, ’root’, ’passWord’ );
 mysql_select_db( ’users’ );

 $res = mysql_query( "SELECT id FROM users WHERE login=’".$name."’" );
 while( $row = mysql_fetch_array( $res ) ) { $id = $row[0]; }

 return $id;
}

var_dump( get_user_id( ’jack’ ) );
?>

  注意使用了 mysql_connect 函数来访问数据库。还要注意查询,其中使用字符串连接来向查询添加 $name 参数。

  该技术有两个很好的替代方案:PEAR DB 模块和 PHP Data Objects (PDO) 类。两者都从特定数据库选择提供抽象。因此,您的代码无需太多调整就可以在 IBM? DB2?、MySQL、PostgreSQL 或者您想要连接到的任何其他数据库上运行。

  使用 PEAR DB 模块和 PDO 抽象层的另一个价值在于您可以在 SQL 语句中使用 ? 操作符。这样做可使 SQL 更加易于维护,且可使您的应用程序免受 SQL 注入攻击。

  使用 PEAR DB 的替代代码如下所示。

  清单 2. Access/get_good.php

<?php
require_once("DB.php");

function get_user_id( $name )
{
 $dsn = ’mysql://root:password@localhost/users’;
 $db =& DB::Connect( $dsn, array() );
 if (PEAR::isError($db)) { die($db->getMessage()); }

 $res = $db->query( ’SELECT id FROM users WHERE login=?’,array( $name ) );
 $id = null;
 while( $res->fetchInto( $row ) ) { $id = $row[0]; }

 return $id;
}

var_dump( get_user_id( ’jack’ ) );
?>

  注意,所有直接用到 MySQL 的地方都消除了,只有 $dsn 中的数据库连接字符串除外。此外,我们通过 ? 操作符在 SQL 中使用 $name 变量。然后,查询的数据通过 query() 方法末尾的 array 被发送进来。

  问题 2:不使用自动增量功能

  与大多数现代数据库一样,MySQL 能够在每记录的基础上创建自动增量惟一标识符。除此之外,我们仍然会看到这样的代码,即首先运行一个 SELECT 语句来找到最大的 id,然后将该 id 增 1,并找到一个新记录。清单 3 展示了一个示例坏模式。

  清单 3. Badid.sql

DROP TABLE IF EXISTS users;
CREATE TABLE users (
id MEDIUMINT,
login TEXT,
password TEXT
);

INSERT INTO users VALUES ( 1, ’jack’, ’pass’ );
INSERT INTO users VALUES ( 2, ’joan’, ’pass’ );
INSERT INTO users VALUES ( 1, ’jane’, ’pass’ );

  这里的 id 字段被简单地指定为整数。所以,尽管它应该是惟一的,我们还是可以添加任何值,如 CREATE 语句后面的几个 INSERT 语句中所示。清单 4 展示了将用户添加到这种类型的模式的 PHP 代码。

  清单 4. Add_user.php

<?php
require_once("DB.php");

function add_user( $name, $pass )
{
 $rows = array();

 $dsn = ’mysql://root:password@localhost/bad_badid’;
 $db =& DB::Connect( $dsn, array() );
 if (PEAR::isError($db)) { die($db->getMessage()); }

 $res = $db->query( "SELECT max(id) FROM users" );
 $id = null;
 while( $res->fetchInto( $row ) ) { $id = $row[0]; }

 $id += 1;

 $sth = $db->PRepare( "INSERT INTO users VALUES(?,?,?)" );
 $db->execute( $sth, array( $id, $name, $pass ) );

 return $id;
}

$id = add_user( ’jerry’, ’pass’ );

var_dump( $id );
?>

  add_user.php 中的代码首先执行一个查询以找到 id 的最大值。然后文件以 id 值加 1 运行一个 INSERT 语句。该代码在负载很重的服务器上会在竞态条件中失败。另外,它也效率低下。

  那么替代方案是什么呢?使用 MySQL 中的自动增量特性来自动地为每个插入创建惟一的 ID。更新后的模式如下所示。

  清单 5. Goodid.php

DROP TABLE IF EXISTS users;
CREATE TABLE users (
 id MEDIUMINT NOT NULL AUTO_INCREMENT,
 login TEXT NOT NULL,
 password TEXT NOT NULL,
 PRIMARY KEY( id )
);

INSERT INTO users VALUES ( null, ’jack’, ’pass’ );
INSERT INTO users VALUES ( null, ’joan’, ’pass’ );
INSERT INTO users VALUES ( null, ’jane’, ’pass’ );

  我们添加了 NOT NULL 标志来指示字段必须不能为空。我们还添加了 AUTO_INCREMENT 标志来指示字段是自动增量的,添加 PRIMARY KEY 标志来指示那个字段是一个 id。这些更改加快了速度。清单 6 展示了更新后的 PHP 代码,即将用户插入表中。

  清单 6. Add_user_good.php

<?php
require_once("DB.php");

function add_user( $name, $pass )
{
 $dsn = ’mysql://root:password@localhost/good_genid’;
 $db =& DB::Connect( $dsn, array() );
 if (PEAR::isError($db)) { die($db->getMessage()); }

 $sth = $db->prepare( "INSERT INTO users VALUES(null,?,?)" );
 $db->execute( $sth, array( $name, $pass ) );

 $res = $db->query( "SELECT last_insert_id()" );
 $id = null;
 while( $res->fetchInto( $row ) ) { $id = $row[0]; }

 return $id;
}

$id = add_user( ’jerry’, ’pass’ );

var_dump( $id );
?>

  现在我不是获得最大的 id 值,而是直接使用 INSERT 语句来插入数据,然后使用 SELECT 语句来检索最后插入的记录的 id。该代码比最初的版本及其相关模式要简单得多,且效率更高。

  问题 3:使用多个数据库

  偶尔,我们会看到一个应用程序中,每个表都在一个单独的数据库中。在非常大的数据库中这样做是合理的,但是对于一般的应用程序,则不需要这种级别的分割。此外,不能跨数据库执行关系查询,这会影响使用关系数据库的整体思想,更不用说跨多个数据库管理表会更困难了。 那么,多个数据库应该是什么样的呢?首先,您需要一些数据。清单 7 展示了分成 4 个文件的这样的数据。

  清单 7. 数据库文件

Files.sql:
CREATE TABLE files (
 id MEDIUMINT,
 user_id MEDIUMINT,
 name TEXT,
 path TEXT
);

Load_files.sql:
INSERT INTO files VALUES ( 1, 1, ’test1.jpg’, ’files/test1.jpg’ );
INSERT INTO files VALUES ( 2, 1, ’test2.jpg’, ’files/test2.jpg’ );

Users.sql:
DROP TABLE IF EXISTS users;
CREATE TABLE users (
 id MEDIUMINT,
 login TEXT,
 password TEXT
);

Load_users.sql:
INSERT INTO users VALUES ( 1, ’jack’, ’pass’ );
INSERT INTO users VALUES ( 2, ’jon’, ’pass’ );

  在这些文件的多数据库版本中,您应该将 SQL 语句加载到一个数据库中,然后将 users SQL 语句加载到另一个数据库中。用于在数据库中查询与某个特定用户相关联的文件的 PHP 代码如下所示。

  清单 8. Getfiles.php

<?php
require_once("DB.php");

function get_user( $name )
{
 $dsn = ’mysql://root:password@localhost/bad_multi1’;
 $db =& DB::Connect( $dsn, array() );
 if (PEAR::isError($db)) { die($db->getMessage()); }

 $res = $db->query( "SELECT id FROM users WHERE login=?",array( $name ) );
 $uid = null;
 while( $res->fetchInto( $row ) ) { $uid = $row[0]; }

 return $uid;
}

function get_files( $name )
{
 $uid = get_user( $name );

 $rows = array();

 $dsn = ’mysql://root:password@localhost/bad_multi2’;
 $db =& DB::Connect( $dsn, array() );
 if (PEAR::isError($db)) { die($db->getMessage()); }

 $res = $db->query( "SELECT * FROM files WHERE user_id=?",array( $uid ) );
 while( $res->fetchInto( $row ) ) { $rows[] = $row; }
 return $rows;
}

$files = get_files( ’jack’ );

var_dump( $files );
?>

  get_user 函数连接到包含用户表的数据库并检索给定用户的 ID。get_files 函数连接到文件表并检索与给定用户相关联的文件行。

  做所有这些事情的一个更好办法是将数据加载到一个数据库中,然后执行查询,比如下面的查询。

  清单 9. Getfiles_good.php

<?php
require_once("DB.php");

function get_files( $name )
{
 $rows = array();

 $dsn = ’mysql://root:password@localhost/good_multi’;
 $db =& DB::Connect( $dsn, array() );
 if (PEAR::isError($db)) { die($db->getMessage()); }

 $res = $db->query("SELECT files.* FROM users, files WHERE
users.login=? AND users.id=files.user_id",
array( $name ) );
 while( $res->fetchInto( $row ) ) { $rows[] = $row; }

 return $rows;
}

$files = get_files( ’jack’ );

var_dump( $files );
?>

  该代码不仅更短,而且也更容易理解和高效。我们不是执行两个查询,而是执行一个查询。

  尽管该问题听起来有些牵强,但是在实践中我们通常总结出所有的表应该在同一个数据库中,除非有非常迫不得已的理由。



添加到del.icio.us 添加到新浪ViVi 添加到百度搜藏 添加到POCO网摘 添加到天天网摘365Key 添加到和讯网摘 添加到天极网摘 添加到黑米书签 添加到QQ书签 添加到雅虎收藏 添加到奇客发现 diigo it 添加到饭否 添加到飞豆订阅 添加到抓虾收藏 添加到鲜果订阅 digg it 貼到funP 添加到有道阅读 Live Favorites 添加到Newsvine 打印本页 用Email发送本页 在Facebook上分享


Disclaimer Privacy Policy About us Site Map

If you have any requirements, please contact webmaster。(如果有什么要求,请联系站长)
Copyright ©2011-
uuhomepage.com, Inc. All rights reserved.