一、简介
PHP中提供的用于MySQL操作的API主要分为三种:即MySQL扩展、mysqli扩展和PDO PHP数据对象。三者各有优缺点。使用建议首选mysqli扩展,下来是PDO,mysql扩展不建议使用。
1.1、PHP的MySQL扩展
这种扩展是PHP应用于MySQL数据库交互的早期扩展,mysql扩展提供了一个面向过程的接口,并且是针对MySQL4.1.3或更早版本设计的,因此,该扩展虽然可以与MySQL4.1.3或更新的数据库服务端进行交互,但是它并不支持后期的MySQL服务端提供的一些特性。如果使用MySQL4.1.3或者更新的服务器版本,强烈建议使用mysqli扩展替换mysql扩展。
1.2、PHP的mysqli扩展
mysqli扩展,有时称之为MySQL增强扩展,可以用于使用MySQL4.1.3或更新版本中新的高级特性,在PHP5以及以后的版本中包含有mysqli扩展,相对于mysql扩展,mysqli扩展主要有以下优势:
1.2.1、面向对象接口
1.2.2、prepared语句支持
1.2.3、多语句执行支持
1.2.4、事务支持
1.2.5、增强的调试能力
1.2.6、嵌入式服务支持
如果使用MySQL4.1.3或者更新的服务器版本,强烈建议使用mysqli扩展替换mysql扩展。
注意:mysqli扩展在提供面向对象接口的同时也提供了一个面向过程的接口,也就是说可以使用mysqli接口编写面向对象的程序也能编写面向过程的程序。
1.3、PDO
PHP数据对象,是PHP的一个数据库抽象规范,PDO提供了一个统一的API接口可以让你的PHP应用不用去关心具体要连接的数据库服务器类型,也就是说,使用PDO的API,你可以在不同数据库类型之间进行无缝切换,仅仅需要修改很少的PHP代码。类似Java中的JDBC。它的优点是提供干净、简单、可移植的API,缺点是会限制你让你不能使用MySQL后期版本提供的数据库高级特性,如MySQL的多语句执行。PDO的MySQL驱动处于PDO的下层,提供特定的MySQL功能,程序员调用PDO的API,而PDO会使用PDO的MySQL驱动完成于MySQL服务器端的交互。PDO的MySQL驱动只是众多PDO驱动中的一个,其他的还有PostgreSQL驱动等。
1.4、关于PHP的MySQL Native驱动
为了和MySQL数据库服务端进行交互,mysql扩展、mysqli扩展以及PDO MySQL驱动都使用了实现了必要协议的底层库,以前,可用的库只有MySQL客户端和libmysql,libmysql是早期为c应用程序设计的,libmysql包含的接口没有针对PHP进行优化,所以,开发了MySQL Native驱动mysqlnd,作为libmysql针对PHP应用的修改优化版本。以上三种扩展都可以配置并使用libmysql或者mysqlnd。由于mysqlnd专门针对PHP进行过优化,它在内存和速度上都比libmysql有较大提升。注意:mysqlnd驱动仅仅可以在MySQL服务端版本为4.1.3及以后的版本中使用。
二、mysql扩展
2.1、插入、更新、删除基本差不多
![]()
扩展查询<?php /* * 建立连接, mysql_connect,打开一个到MySQL服务器的连接, * 失败返回false, * 成功返回一个MySQL连接标识 */ $db = mysql_connect("127.0.0.1","root","root123"); if(!$db){ die('连接建立错误: ' . mysql_error()); } echo "客户端信息:".mysql_get_client_info()."<br />";//客户端信息 echo "主机信息:".mysql_get_host_info()."<br />";//主机信息 echo "服务器信息:".mysql_get_server_info()."<br />";//服务器信息 echo "协议:".mysql_get_proto_info()."<br />";//协议 if(!mysql_select_db("php")){//选择数据库,成功返回true,失败返回false die('数据库选择错误: ' . mysql_error()); } $querySQL = "select * from php";//查询字符串 /* * 发送一条MySQL查询,仅对SELECT,SHOW,EXPLAIN,DESCRIBE语句返回一个资源标识符,查询不正确则返回false, * 对于其它类型的SQL语句,mysql_query()执行成功时返回true,出错时返回false。 * 非false的返回值代表查询时合法的并且能被服务器执行,但并不表示影响到的行数或返回的行数, * 因为一条查询有可能执行成功了但并不返回或者影响到任何行。 */ $result = mysql_query($querySQL); //echo $result; if($result != false){//查询成功 /* * 从结果集里获取数据 * mysql_fetch_array:从结果集里获取一行作为关联数组、或索引数组或者而这兼有。 * 没有更多则返回false。 */ while($row = mysql_fetch_array($result)){ echo $row[0]."\t".$row['name']."<br />";//既可以采用索引数组方式访问,又可以采用关联数组方式访问。 } /* * 将指定的结果标识所关联的 MySQL 结果内部的行指针移动到指定的行号。 * row_number 从 0 开始。row_number 的取值范围应该从 0 到 mysql_num_rows - 1。 * 但是如果结果集为空(mysql_num_rows() == 0),要将指针移动到 0 会失败并发出 E_WARNING 级的错误, * mysql_data_seek() 将返回 FALSE。 * 由于此处有结果集,所以不进行mysql_num_rows()判断 */ mysql_data_seek($result, 0); /* * 从结果集中取得一行作为关联数组 ,只能通过字段名访问,字段名区分大小写。 * 没有更多则返回false。 */ while($row = mysql_fetch_assoc($result)){ echo $row['id']."\t".$row['name']."<br />"; } mysql_data_seek($result, 0);//再次移动指针 /* * 从结果集中取得一行作为对象,只能通过字段名访问 * 没有更多则返回false。 */ while($row = mysql_fetch_object($result)){ echo $row->id."\t".$row->name."<br />"; } mysql_data_seek($result, 0);//再次移动指针 /* * 从结果集中取得一行作为枚举数组,只能通过索引访问 * 没有更多则返回false。 */ while($row = mysql_fetch_row($result)){ echo $row[0]."\t".$row[1]."<br />"; } } mysql_free_result($result);//释放结果集内存,成功返回true,失败返回false, mysql_close($db);//关闭连接,成功返回true,失败返回false。 ?>
2.2、插入、更新、删除基本差不多
![]()
mysql扩展插入 更新 删除<?php /* * 建立连接, mysql_connect,打开一个到MySQL服务器的连接, * 失败返回false, * 成功返回一个MySQL连接标识 */ $db = mysql_connect("127.0.0.1","root","root123"); if(!$db){ die('连接建立错误: ' . mysql_error()); } if(!mysql_select_db("php")){//选择数据库,成功返回true,失败返回false die('数据库选择错误: ' . mysql_error()); } $insertSQL = "insert into php values(4,'phpinsert')";//插入语句 $updateSQL = "update php set name='updatephp' where id = 4";//修改语句 $deleteSQL = "delete from php where id = 2"; /* * 发送一条MySQL查询,仅对SELECT,SHOW,EXPLAIN,DESCRIBE语句返回一个资源标识符,查询不正确则返回false, * 对于其它类型的SQL语句,mysql_query()执行成功时返回true,出错时返回false。 * 非false的返回值代表查询时合法的并且能被服务器执行,但并不表示影响到的行数或返回的行数, * 因为一条查询有可能执行成功了但并不返回或者影响到任何行。 */ $insertresult = mysql_query($insertSQL); if($insertresult != false){//查询成功 /* * 取得最近一次与 link_identifier 关联的 INSERT,UPDATE 或 DELETE 查询所影响的记录行数。 * 执行成功则返回受影响的行的数目,如果最近一次查询失败的话,函数返回 -1。 */ $number = mysql_affected_rows(); echo "插入影响行数:".$number."<br />"; /* * 取得上一步 INSERT 操作产生的 ID ,返回上一步 INSERT 查询中产生的 AUTO_INCREMENT 的 ID 号, * 如果上一查询没有产生 AUTO_INCREMENT 的值,则 mysql_insert_id() 返回 0。 * 如果需要保存该值以后使用,要确保在产生了值的查询之后立即调用 mysql_insert_id()。 * 此处由于没有 AUTO_INCREMENT,所以返回0。 */ echo mysql_insert_id()."<br />"; } $updateresult = mysql_query($updateSQL); if($updateresult !=FALSE){//更新操作 $number = mysql_affected_rows();//大于0则成功 echo "更新影响行数:".$number."<br />"; } $deleteresult = mysql_query($deleteSQL); if($deleteresult !=FALSE){//更新操作 $number = mysql_affected_rows(); //大于0则成功 echo "删除影响行数:".$number."<br />"; } mysql_close($db);//关闭连接,成功返回true,失败返回false。 ?>
三、mysqli扩展
3.1、mysqli过程化查询
![]()
mysqli过程化查询<?php /* * 建立连接, mysqli_connect,打开一个到MySQL服务器的连接, * 失败返回false, * 成功返回一个MySQL连接标识 */ $db = mysqli_connect("127.0.0.1","root","root123","php"); if(mysqli_connect_errno()){//mysqli_connect_errno(),返回mysqli_connect()的错误号,如果没出错,返回0 die('连接建立错误: ' . mysqli_connect_error() );//返回mysqli_connect()的错误描述 } $querySQL = "select * from php";//查询字符串 /* *失败返回false,SELECT, SHOW, DESCRIBE 或者 EXPLAIN查询语句将返回mysqli_result 对象 *其他语句返回true * 此处,过程化编程需要$db参数。 */ $result = mysqli_query($db,$querySQL); //echo $result; if($result != false){//查询成功 /* * 从结果集里获取数据 * mysqli_fetch_array:从结果集里获取一行作为关联数组、或索引数组或者而这兼有。 * 没有更多则返回false。 */ while($row = mysqli_fetch_array($result)){ echo $row[0]."\t".$row['name']."<br />";//既可以采用索引数组方式访问,又可以采用关联数组方式访问。 } /* * 将指定的结果标识所关联的 MySQL 结果内部的行指针移动到指定的行号。 * row_number 从 0 开始。row_number 的取值范围应该从 0 到 mysqli_num_rows - 1。 * 但是如果结果集为空(mysqli_num_rows() == 0),要将指针移动到 0 会失败并发出 E_WARNING 级的错误, * mysqli_data_seek() 将返回 FALSE。 * 由于此处有结果集,所以不进行mysqli_num_rows()判断 */ mysqli_data_seek ($result, 0); /* * 从结果集中取得一行作为关联数组 ,只能通过字段名访问,字段名区分大小写。 * 没有更多则返回false。 */ while($row = mysqli_fetch_assoc($result)){ echo $row['id']."\t".$row['name']."<br />"; } mysqli_data_seek ($result, 0);//再次移动指针 /* * 从结果集中取得一行作为对象,只能通过字段名访问 * 没有更多则返回false。 */ while($row = mysqli_fetch_object($result)){ echo $row->id."\t".$row->name."<br />"; } mysqli_data_seek ($result, 0);//再次移动指针 /* * 从结果集中取得一行作为枚举数组,只能通过索引访问 * 没有更多则返回false。 */ while($row = mysqli_fetch_row($result)){ echo $row[0]."\t".$row[1]."<br />"; } } mysqli_free_result($result);//释放结果集内存,成功返回true,失败返回false, mysqli_close($db);//关闭连接,成功返回true,失败返回false。 ?>
3.2、mysqli预处理插入,修改和删除类似
![]()
mysqli预处理插入<?php $db = mysqli_connect("127.0.0.1","root","root123","php"); if(mysqli_connect_errno()){//mysqli_connect_errno(),返回mysqli_connect()的错误号,如果没出错,返回0 die('连接建立错误: ' . mysqli_connect_error() );//返回mysqli_connect()的错误描述 } $updateSQL = "insert into php values(?,?)";//插入字符串 if(!mysqli_autocommit($db,FALSE)){//事务性,关闭自动提交 echo "自动提交关闭失败"."<br />"; } //对语句进行预处理,成功返回statement对象句柄 $stmt = mysqli_prepare($db,$updateSQL); if($stmt == FALSE){ echo "预处理失败"."<br />"; } //绑定数据 //第二个参数是参数类型,i代表整型,s代表字符串型,d浮点型,b blob型 //成功返回true,失败返回flase //后面的参数是变量,注意只能是变量不能使值 if(!mysqli_stmt_bind_param($stmt,"is",$id,$name)){ echo "绑定数据失败"."<br />"; } //赋值 $id = 5; $name = "prepareinsert"; /* * 执行预处理语句,成功返回true,失败返回false。 */ if(mysqli_stmt_execute($stmt)){ echo mysqli_affected_rows($db); //获取影响的行数,注意,要在提交事务之前获取,不能卸载提交事务之后 mysqli_commit($db);//提交事务 }else{ mysqli_rollback($db);//回滚事务 } mysqli_stmt_close($stmt); mysqli_close($db); ?>
3.3、mysqli面向对象,包含结果集绑定
![]()
mysqli面向对象<?php $mysqli = new mysqli("127.0.0.1","root","root123","php"); $selectSQL = "select * from php where id > ?"; $queryStmt = $mysqli->prepare($selectSQL);//预处理语句 $queryStmt->bind_param("i", $id);//参数绑定 $id = 2; $queryStmt->bind_result($id,$name);//结果集绑定 $queryStmt->execute();//执行 $queryStmt->store_result();//存储结果 $result = $queryStmt->result_metadata();//获取meta信息 while($field = $result->fetch_field()){//获取列 echo $field->name; } echo "<br />"; while($queryStmt->fetch()){//获取数据 echo $id,$name."<br />"; } echo "记录数:".$queryStmt->num_rows;//记录数 $queryStmt->free_result();//释放结果集内存 $queryStmt->close();//关闭预处理 $mysqli->close();//关闭连接 ?>