陈力:传智播客古代 珍宝币 泡泡龙游戏开发第39讲:PHP数据库编程MySQLi扩展库
mysqli扩展允许我们访问MySQL 数据库,并对MySql数据库进行curd操作。mysqli扩展可以进行数据查询、批量执行sql语句、事务回滚、预处理 MySQLi_STMT等操作。请贵阳网站建设的朋友继续往下读。
一、mysql数据库
mysqli (mysql improve mysql扩展库的增强版)。mysqli扩展允许我们访问MySQL 数据库,并对MySql数据库进行curd操作。可以使用php 的mysqli扩展库去操作mysql数据库。
mysql扩展库和mysqli扩展库的比较:这两个都是php设计者给我们提供的扩展库。都可以完成对mysql数据库的操作。mysqli扩展库是mysql扩展库的改进版本。mysqli 的稳定性和安全性,效率有所提高。mysqi支持面向对象编程,同时mysqli扩展库考虑到php老程序员,提供面向过程的编程风格(mysqli有两套编程风格)。
通过mysqli建立连接($conn):
(1)$mysqli=new MySQLi(“主机名”,“用户名”,“密码”,“数据库");
if (mysqli_connect_error()) {
die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
}
(2)$mysqli = mysqli_init();
if (!$mysqli) {
die('mysqli_init failed');}
if (!$mysqli->real_connect('localhost', 'root', 'root', 'test')) {
die('Connect Error ('. mysqli_connect_errno() . ') '. mysqli_connect_error());}
mysqli 编程入门实例:
编写一个程序,这个程序从user1表中读取数据,并打印在网页中。(使用mysqli完成)。
步骤1:先使用mysqli面向对象的风格,完成案例。
步骤2:配置php.ini 文件让php支持mysqli扩展库。
extension=php_mysqli.dll
步骤3:进行数据库创建,新建表结构。
步骤4:编写代码。
<?php
header("Content-type: text/html;charset=utf-8");
//mysqli操作mysql数据库(面向对象风格)
//1.创建MySQLi 对象
$mysqli=new MySQLi("localhost","root","root","test");
//验证是否成功
if($mysqli->connect_error){
die("连接失败".$mysqli->connect_error);
}
$sql="select * from user1";//2. 操作数据库(发送sql)
$res=$mysqli->query($sql); //$res 是结果集,类型为mysqli result
//var_dump($res);
//3. 处理结果 mysql_fetch_row();
while($row=$res->fetch_row()){
foreach($row as $key=>$val){
echo "--$val";
}
echo "<br/>";
}
$res->free();//4. 关闭资源//释放内存
$mysqli->close();//关闭连接
?>
使用面向过程的方式实现代码:
<?php
header("Content-type: text/html;charset=utf-8");
$mysqli=mysqli_connect("localhost","root","root","test");//1.得到mysqli连接
if(!$mysqli){
die("连接失败".mysqli_connnect_error($mysqli));
}
//2.向数据库发送sql语句(ddl,dml dql ...)
$sql="select * from user1";
$res=mysqli_query($mysqli,$sql);
//var_dump($res);
//3.处理得到的结果
//循环取出$res中的数据mysqli_fetch_row mysql_fetch_row
while($row=mysqli_fetch_row($res)){
foreach($row as $key=>$val){
echo "--$val";
}
echo "<br/>";
}
mysqli_free_result($res); //4.关闭资源
mysqli_close($mysqli);
?>
程序中的$res用于代表Sql语句的执行结果。
(1) 如果执行的是dml语句,则返回bool 。
(2) 如果执行的是dql语句,则返回查询结果MySQLi_Result 结果集对象。
(3) 如何从mysql result 取出查询的结果,在mysqli 扩展中,也提供了四种方式来获取mysqli result结果集:
mysqli_result::fetch_assoc <==> mysql_fetch_assoc
mysqli_result::fetch_row <==> mysql_fetch_row
mysqli_result::fetch_array <===> mysql_fetch_array
mysqli_result::fetch_object<===> mysql_fetch_object
通过var_dump($res) 我们可以更加清楚的知道,当执行查询的时候,mysql_query() 返回 mysql result 类型,执行dml语句返回bool类型。
取出数据结果集有四种方式(mysql_fetch_row,,mysql_fetch_assoc, mysql_fetch_array, ,mysql_fetch_object) 区别?如何选择使用问题?
区别:前两个效率相当:mysql_fetch_row从结果集中取得一行作为索引数组 mysql_fetch_assoc 取出关联数组(需要通过列名来取数据)。
第三个效率偏低:因为mysql_fetch_array从结果集中取得一行作为关联数组和数字数组二者兼有,因此代价高,不推荐使用可用通过print_r或者var_dump来测试。
第四个一般我们不用:因为我们往往自定义对象来处理: mysql_fetch_object 从结果集中取得一行作为对象。
取出结果集中的数据除了该ppt列举出的案例外:还可以使用如下方法:
while(list($id,$name,$passwd)=mysql_fetch_row($result)){ //这里不能使用mysql_fetch_assoc().必须包含索引数组才可以
echo $id.$name,$passwd;
}
while($row=mysql_fetch_row($result)){ //这里能使用mysql_fetch_assoc(),或者mysql_fetch_array()
foreach($row as $val){
echo $val.”-”;
}
}
数据库的连接是非常稀有的资源,用完后要及时释放,如果不能及时、正确的关闭,极易导致系统宕机。使用原则是尽量晚创建,尽量早的释放。
在mysqli释放结果集有三种方式:
void mysqli_result::free ( void )
void mysqli_result::close ( void )
void mysqli_result::free_result ( void )
面向对象风格:
bool mysqli::close ( void )
过程化风格:
bool mysqli_close ( mysqli $link )
mysql的sql 语句的特别说明:如果操作的字段类型是string型,则要求我们的要用‘’包括。如果操作的字段类型是 数值型,则可以用’80’包括,也可以不用。
二、对mysql数据库进行CRUD
mysqli::query用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个函数向数据库发送增删改查语句即可。
对users表的增删改操作:
$mysqli=new MySQLi("localhost","root","root","test");
if (mysqli_connect_errno()) {
die("Connect failed: ". mysqli_connect_error());
}
echo $mysqli->server_info."<br/>";
//如果是查询数据库
//$sql="select *from user1";
$sql="delete from user1 where id=90";
//$sql可以是 insert 和 update
$mysqli->query(“set names gbk”); //这个设置很重要
$res=$mysqli->query($sql);
//证明返回类型是什么
var_dump($res);
//判断需要技巧
if(!$res){
echo '失败.'.$mysqli->error;
exit();
}
//看看受影响的行数
if($mysqli->affected_rows>0){
echo '执行成功!';
}else{
echo '记录没有改变';
}
$mysqli->close();
三、mysqli扩展库增强--批量执行sql语句
有时我们需要一次性执行多条sql语句,比如批量增加用户,这时如果单条单条的向mysql数据库发送sql指令,效率不高,这时可以考虑使用批量执行sql语句的方式。
基本使用:
$sqls=“sql语句1;sql语句2;sql语句n”;
$res=mysqli::multi_query($sqls)
说明:如果$sqls是dml语句,则$res返回bool,
如果$sqls是dql语句,则$res返回多个结果集,需要使用 mysqli::store_result
和 mysqli::next_result配合取出各个结果集。
案例:
请使用mysqli的mysqi::multi_query() 一次性添加三个用户 宋江 卢俊义 吴用。
代码:
<?php
//1.得到mysqli对象
$mysqli=new MySQLi("localhost","root","hsp123","test");
if($mysqli->connect_error){
die($mysqli->connect_error);
}
$sqls="insert into user1 (name,password,email,age) values('宋江','aaa','aa@shu.com',45);";
$sqls.="insert into user1 (name,password,email,age) values('卢俊义','aaa','aa@shu.com',45);";
$sqls.="insert into user1 (name,password,email,age) values('吴用','aaa','aa@shu.com',45);";
//$sqls.="update ;";
//$sqls.="delete ;";
$b=$mysqli->multi_query($sqls);
if(!$b){
echo "执行失败".$mysqli->error;
}else{
echo "ok";
}
$mysqli->close();//关闭资源
?>
批量执行dml语句可以混合使用 delete insert update,但是最好不要使用select。
批量执行 dql语句:它的作用是可以一次性的取回多个结果集。
案例:
请使用mysqli的mysqi::multi_query()一次性查询并显示①users表的结构、② users表中用户id ,和用户名字。
<?php
$mysqli=new MySQLi("localhost","root","hsp123","test");//1.得打mysqli对象
$sqls="select * from emp;"; //2.批量查询
$sqls.="select * from user1;";
$sqls.="desc user1";
3.处理结果,如果成功,则至少有一个结果集
if($res=$mysqli->multi_query($sqls)){
do{
$result=$mysqli->store_result();//从mysqli连接取出第一个结果集
//显示mysqli result对象
while($row=$result->fetch_row()){
foreach($row as $key => $val){
echo "--$val";
}
echo "<br/>";
}
//及时释放$result;
$result->free();
if(!$mysqli->more_results()){
break;
}
echo "<br/>******新的结果集*******<br/>";
}while($mysqli->next_result());
}
$mysqli->close();//4.关闭资源
?>
四、mysql的事务处理
事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败。如:网上转账就是典型的要用事务来处理,用以保证数据的一致性。
为什么需要事务控制,请大家先看下面的一个应用场景:
银行转账业务:
有一张银行账号表
create table account
(id int primary key,
balance float);
现在有一段php程序,要完成把1号1元钱,转到2号账号上。
********模拟有转账错误的代码*******
<?php
//模拟出现转账业务的代码:
$mysqli=new MySQLi("localhost","root","root","test");
if (mysqli_connect_error()) {
die('Connect Error '. mysqli_connect_error());
}
$sql1="update account set balance=balance-1 where id=1";
//这里我们模拟一个错误
$sql2="update account2 set balance=balance+1 where id=2";
$res1=$mysqli->query($sql1);
$res2=$mysqli->query($sql2);
if(!$res1 || !$res2){
echo '没有全部执行成功!';
}
$mysqli->close();
?>
这时我们需要有一种方法来控制两句sql语句同时成功,同时失败的时候的处理。方法是使用事务控制来解决这个问题。
如何进行事务控制,针对上一个实际问题,提出解决方案。新的概念: 事务的提交commit 和 事务的回滚 rollback。
<?php
//模拟出现转账业务的代码:
$mysqli=new MySQLi("localhost","root","root","test");
if (mysqli_connect_error()) {
die('Connect Error '. mysqli_connect_error());
}
$mysqli->autocommit(false);
$sql1="update account set balance=balance-1 where id=1";
//这里我们模拟一个错误
$sql2="update account set balance=balance+1 where id=2";
$res1=$mysqli->query($sql1);
$res2=$mysqli->query($sql2);
if(!$res1 || !$res2){
echo '有语句执行失败,回滚!';
$mysqli->rollback();//
}else{
echo '确定提交';
$mysqli->commit();
}
$mysqli->close();
?>
在mysql控制台可以使用事务来操作,具体步骤如下:
1)开启一个事务:start transaction
2)做保存点:savepoint 保存点名称
3)操作....
4)可以回滚(也可以提交),如果没有问题就提交。
commit
如果你觉得有问题,就回滚:rollback to 保存点。
事务的acid特性:原子性,一致性,持久性,隔离性。
五、mysqli扩展库增强--预处理 MySQLi_STMT
现在需要向mysql数据库添加100个用户,请问如何实现?
思路:
1. 发送100个 insert语句 ,频繁连接数据库和对sql语句编译都导致效率低下。
2. 一次性发送 100个insert语句,虽然只需要连接一次数据库,但是仍然要在数据库server编译多个sql语句,效率仍然低。
3. 使用预处理语句 MySQLi_STMT { (编译一次,执行多次)
使用预处理语句有什么好处?
与传统的执行sql语句相比有如下优点:效率高,执行速度快,安全性高,可以防止sql注入。
使用预处理语句快速入门案例:
执行dml 语句(没有结果集返回),需求: 请使用预处理的方式,向数据库添加三个用户。
执行dql 语句(有结果集返回):需求: 请使用预处理的方法,查询所有id>5的用户 的id,name,email,(id可能变化)。
需求: 请使用预处理的方式,查询id=4 密码 为 12345的用户信息,看看能否防止sql注入。
*******使用预处理语句完成dml******
<?php
$mysqli=new mysqli("localhost","root","root","test");
if(mysqli_connect_errno()){
die ('失败'.mysqli_connect_error());
}
$mysqli->query("set names utf8");
$sql="insert into user1 (name,email,password) values(?,?,?)";
$stm=$mysqli->prepare($sql);
//给?号绑定值
$name="张三";
$email="bayu@163.com";
$password="123456";
$stm->bind_param("sss",$name,$email,$password);
$b=$stm->execute();
$name="张三2";
$email="bayu2@163.com";
$password="1234567";
$b=$stm->execute();
$name="张三3";
$email="bayu3@163.com";
$password="1234567";
$b=$stm->execute();
if($b){
echo '成功!';
}else{
die('失败'.$stm->error);
}
$stm->close();
$mysqli->close();
?>
*****使用预处理完成select语句dql********************
<?php
$mysqli=new mysqli("localhost","root","root","test");
if(mysqli_connect_errno()){
die ('失败'.mysqli_connect_error());
}
$mysqli->query("set names utf8");
$sql="select id,name,email from user1 where id>?";
$stm=$mysqli->prepare($sql) ;
//给?号绑定值
$id=10;
$stm->bind_param("i",$id);
//预处理执行时,返回bool,没有返回结果集对象,因此绑定结果到某变量
$stm->bind_result($id,$name,$email);
//执行
$stm->execute();
//取出结果集本身信息(可以不用讲解)
$res=$stm->result_metadata();
//var_dump($res);//$res 的类型就是 mysqli result
while($field_info=$res->fetch_field()){
echo "{$field_info->name}--";
}
echo "<br/>";
//取出记录结果
$stm->store_result();
while($stm->fetch()){
echo "<br/>$id--$name--$email";
}
$stm->free_result();
$stm->close();
$mysqli->close();
?>
*********查询用户id和密码,讲解预处理尅防止sql注入************************
<?php
$mysqli=new mysqli("localhost","root","root","test");
if(mysqli_connect_errno()){
die ('失败'.mysqli_connect_error());
}
$mysqli->query("set names utf8");
$sql="select id,name,email from user1 where id=? and password=?";
$stm=$mysqli->prepare($sql) ;
//给?号绑定值
$id=1;
$password="123456' or 1='1";
$stm->bind_param("is",$id,$password);
//预处理执行时,返回bool,没有返回结果集对象,因此绑定结果到某变量
$stm->bind_result($id,$name,$email);
//执行
$stm->execute();
//取出结果集本身信息(可以不用讲解)
$res=$stm->result_metadata();
//var_dump($res);//$res 的类型就是 mysqli result
while($field_info=$res->fetch_field()){
echo "{$field_info->name}--";
}
echo "<br/>";
//取出记录结果
$stm->store_result();
while($stm->fetch()){
echo "<br/>$id--$name--$email";
}
$stm->free_result();
$stm->close();
$mysqli->close();
?>
使用预编译技术完成查询任务..-》如何封装..项目中说.
<?php
//预编译演示
//需求: 请使用预处理的方式,从数据库查询
//使用预处理的方法,查询所有id>5的用户 的id,name,email
$mysqli=new MySQLi("localhost","root","hsp123","test");
if(mysqli_connect_error()){
die(mysqli_connect_error());
}
//创建一个预定义的对象 ?占位
$sql="select id,name,email from user1 where id>?";
$mysqli_stmt=$mysqli->prepare($sql);
$id=5;
//绑定参数
$mysqli_stmt->bind_param("i",$id);
//绑定结果集
$mysqli_stmt->bind_result($id,$name,$email);
//执行
$mysqli_stmt->execute();
//取出绑定的值
while($mysqli_stmt->fetch()){
echo "<br/>--$id--$name--$email";
}
//还想执行另一个sql
echo "<br/>***********************************";
$id=10;
//绑定参数
$mysqli_stmt->bind_param("i",$id);
//绑定结果集
//执行
$mysqli_stmt->execute();
//取出绑定的值
while($mysqli_stmt->fetch()){
echo "<br/>--$id--$name--$email";
}
//关闭资源
//释放结果
$mysqli_stmt->free_result();
//关闭预编译语句
$mysqli_stmt->close();
//关闭连接
$mysqli->close();
?>
现在我们看看mysqli的一些其他常用函数:
案例: 编写一函数,接收一个表名,然后把表头和表数据,显示页面
<?php
function showTable($table_name){
$mysqli=new MySQLi("localhost","root","hsp123","test");
if(mysqli_connect_error()){
die(mysqli_connect_error());
}
//$sql="select * from $table_name";
$sql="desc user1";
$res=$mysqli->query($sql);
//如何获取返回总行数和列数
echo "共有 行".$res->num_rows." -列=".$res->field_count;
echo "<table border='1'><tr>";
//如何取出表头,从$res取出
while($field=$res->fetch_field()){
echo "<th>{$field->name}</th>";
}
echo "</tr>";
//循环取出数据
while($row=$res->fetch_row()){
echo "<tr>";
foreach($row as $val){
echo "<td>$val</td>";
}
echo "</tr>";
}
echo "</table>";
//关闭资源
$res->free();
$mysqli->close();
}
showTable("user1");
?>
【推荐阅读】陈力:传智播客古代 珍宝币 泡泡龙游戏开发第39讲:PHP数据库编程MySQLi扩展库