zoukankan      html  css  js  c++  java
  • MySQL数据库之PDO扩展

    PDO概述

    • 连接数据库方式

      • mysql扩展 (这种方式php7已经淘汰)
      • mysqli扩展
      • PDO扩展
    • PDO介绍

      • PDO(PHP Data Object)扩展为PHP访问各种数据库提供了一个轻量级,一致性的接口
      • 无论访问什么数据库,都可以通过一致性的接口去操作
    • 开启PDO扩展

      • 开启PDO连接MySQL扩展
      • extension=php_pdo_mysql.dll
    • PDO核心类

      • PDO 表示PHP和数据库之间的一个连接
      • PDOStatement
        • 表示执行数据查询语句(select ,show)后的相关结果集
        • 预处理对象
      • PDOException 表示PDO的异常

    实例化PDO对象

    • 语法
      • __construct($dsn,用户名,密码)

    DSN

    • 概念

      • DSN:data source name
      • 数据源名称,包含的是连接数据库的信息
    • 格式

      • $dsn=数据库类型:host=主机地址;port=端口号;dbname=数据库名称;charset=字符集
    • 数据库类型

      • MySQL数据库 => mysql:
      • oracle数据库 => oci:
      • SQL Server => sqlsrv:

    实例化PDO

    • 概念
      • 实例化PDO的过程就是连接数据库的过程
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    var_dump($pdo);
    ?>
    

    参数省略

    • 参数省略
      • 如果连接的是本地数据库,host可以省略
      • 如果使用的是3306端口,port可以省略
      • charset也省略,如果省略,使用的是默认字符编码
      • dbname也可以省略,如果省略就没有选择数据库
      • host、port、dbname、charset不区分大小写,没有先后顺序
      • 驱动名称不能省略,冒号不能省略(因为冒号是驱动名组成部分),数据库驱动只能小写
    <?php
    $dsn='mysql:';
    $pdo=new PDO($dsn,'root','');
    var_dump($pdo); 
    ?>
    

    使用PDO

    执行数据操作语句

    • 语法
      • $pdo->exec($sql)
      • 执行数据增、删、改语句
      • 执行成功返回受影响的记录数
      • 如果SQL语句错误返回false

    执行增加

    <?php
    $dsn='mysql:host=localhost;port=3306;dbname=sel;charset=utf8';
    $pdo=new PDO($dsn,'root','');
    if($pdo->exec("insert into news values (null,'基本知识','第6章',unix_timestamp())")){
        echo '自动增长的编号是:'.$pdo->lastInsertId(),'<br>';
    } 
    ?>
    

    执行删除

    <?php
    $dsn='mysql:host=localhost;port=3306;dbname=sel;charset=utf8';
    $pdo=new PDO($dsn,'root','');
    if($pdo->exec('delete from news where id=13')){
        echo 'delete success ^_^';
    }
    ?>
    

    执行修改

    <?php
    $dsn='mysql:host=localhost;port=3306;dbname=sel;charset=utf8';
    $pdo=new PDO($dsn,'root','');
    if($pdo->exec("update news set title='准备知识' where id in (3,4)")){
        echo 'update success ^_^';
    }
    ?>
    

    优化写法

    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=sel;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    
    $sql= "update news set title='基本知识' where id in (3,4)";
    $rs= $pdo->exec($sql);
    if($rs){
        echo 'SQL语句执行成功<br>';
        if(substr($sql, 0,6)=='insert')
            echo '自动增长的编号是:'.$pdo->lastInsertId (),'<br>';
        else
            echo '受到影响的记录数是:'.$rs,'<br>';
    }elseif($rs===0){
        echo '数据没有变化<br>';
    }elseif($rs===false){
        echo 'SQL语句执行失败<br>';
        echo '错误编号:'.$pdo->errorCode(),'<br>';
        echo '错误信息:'.$pdo->errorInfo()[2];
    }
    ?>
    

    执行数据查询语句

    • 语法

      • $pdo->query($sql)
      • 返回的是PDOStatement对象
    • 获取二维数组

      • $rs=$stmt->fetchAll(); 默认返回关联和索引数组
      • $rs=$stmt->fetchAll(PDO::FETCH_BOTH); 返回关联和索引数组
      • $rs=$stmt->fetchAll(PDO::FETCH_NUM); 返回索引数组
      • $rs=$stmt->fetchAll(PDO::FETCH_ASSOC); 返回关联数组
      • $rs=$stmt->fetchAll(PDO::FETCH_OBJ); 返回对象数组
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetchAll();
    var_dump($rs);
    ?>
    
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetchAll(PDO::FETCH_BOTH);
    var_dump($rs);
    ?>
    
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetchAll(PDO::FETCH_NUM);
    var_dump($rs);
    ?>
    
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetchAll(PDO::FETCH_ASSOC);
    var_dump($rs);
    ?>
    
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetchAll(PDO::FETCH_OBJ);
    var_dump($rs);
    ?>
    
    • 获取一维数组
      • $rs=$stmt->fetch(); 关联和索引数组
      • $rs=$stmt->fetch(PDO::FETCH_NUM); 索引数组
      • $row=$stmt->fetch(PDO::FETCH_ASSOC) 关联数组
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetch(); 
    var_dump($rs);
    ?>
    
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    $rs=$stmt->fetch(PDO::FETCH_NUM); 
    var_dump($rs);
    ?>
    
    # 通过while循环获取所有数据
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
        $rs[]=$row;
    }
    var_dump($rs);
    ?>
    
    • 匹配列
      • 匹配当前行的第n列,列的编号从0开始,匹配完毕后指针下移一条
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    for($i=0; $i<$stmt->columnCount(); $i++){
        echo $stmt->fetchColumn($i).'<br>';
    }
    ?>
    
    • 总行数与总列数
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    echo '总行数:'.$stmt->rowCount(),'<br>';
    echo '总列数:'.$stmt->columnCount();
    ?>
    
    • 遍历PDOStatement对象
      • PDOStatement对象是有迭代器的
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $stmt=$pdo->query('select * from products');
    foreach($stmt as $row){
        echo $row['proname'],'-',$row['proprice'],'<br>';
    }
    ?>
    

    PDO操作事务

    • 概念

      • 事务:是一个整体,要么一起执行,要么一起回滚
      • 事务的特性:原子性,一致性,隔离性,永久性
      • 需要将多个SQL语句作为一个整体执行,就需要使用到事务
    • MySQL 事务语法

      • start transaction 开启事务
      • begin 开启事务
      • commit 提交事务
      • rollback 回滚事务
    • PDO 事务语法

      • $pdo->beginTransaction() 开启事务
      • $pdo->commit () 提交事务
      • $pdo->rollBack() 回滚事务
    # 创建测试数据表
    <?php
    $dsn= 'mysql:host=localhost;port=3306;dbname=data;charset=utf8';
    $pdo= new PDO($dsn,'root','');
    $pdo->beginTransaction();
    $flag0= $pdo->exec("delete from bank");
    $flag1= $pdo->exec("drop table bank");
    $flag2= $pdo->exec("create table bank(cardid char(4) primary key comment '卡号',balance decimal(10,2) not null comment '余额')engine=innodb charset=utf8 comment '银行卡号表'");
    $flag3= $pdo->exec("insert into bank values ('1001',1000),('1002',1)");
    if($flag2==0 && $flag3){
        $pdo->commit();    
        echo '数据表创建成功!';
    }else{ 
        $pdo->rollBack();
        echo '数据表创建失败!';
    }
    ?>
    
    # PDO操作事务
    <body>
    <?php
    if(!empty($_POST)){
        $dsn='mysql:dbname=sel;charset=utf8';
        $pdo=new PDO($dsn,'root','');
        $out=$_POST['card_out'];    //转出卡号
        $in=$_POST['card_in'];      //注入卡号
        $money=$_POST['money'];     //金额
        $pdo->beginTransaction();   //开启事务
        //转账
        $flag1=$pdo->exec("update bank set balance=balance-$money where cardid='$out'");
        $flag2=$pdo->exec("update bank set balance=balance+$money where cardid='$in'");
        //查看转出的账号是否大于0,大于0返回true,否则返回false
        $stmt=$pdo->query("select balance from bank where cardid='$out'"); 
        $flag3=$stmt->fetchColumn()>=0?1:0;
        if($flag1 && $flag2 && $flag3){
            $pdo->commit ();    //提交事务
            echo '转账成功';
        }
        else{
            $pdo->rollBack ();  //回滚事务
            echo '转账失败';
        }
    }
    ?>
    <form action="" method="post">
        转出卡号: <input type="text" name="card_out" id=""> <br>
        转入卡号: <input type="text" name="card_in" id=""> <br>
        金额:<input type="text" name="money" id=""> <br>
        <input type="submit" value="提交">
    </form>
    </body>
    

    PDO操作预处理

    • MySQL中的预处理

      • 预处理好处:编译一次多次执行,用来解决一条SQL语句多次执行的问题,提高了执行效率
      • 预处理语句
        • prepare 预处理名字 from 'sql语句'
      • 执行预处理
        • execute 预处理名字 [using 变量]
    • PDO中的预处理

      • 位置占位符 insert into bank values (?,?)
      • 参数占位符 insert into bank values (:p1,:p2)
      • $stmt->bindParam()$stmt->bindValue()的区别
        • $stmt->bindParam() 中的值只能是变量
        • $stmt->bindValue() 中的值能是变量也可以为值
      • 预处理的好处
        • 提高执行效率
        • 提高安全性
    # 位置占位符
    <?php
        $dsn= 'mysql:host=localhost;port=3306;dbname=sel;charset=utf8';
        $pdo= new PDO($dsn,'root','');
        //创建预处理对象
        $stmt=$pdo->prepare("insert into bank values (?,?)");   //?是占位符
        //执行预处理
        $cards=[
            ['1003',500],
            ['1004',100]
        ];
        foreach($cards as $card){
            //绑定参数,并执行预处理,
            //方法一:
            /*
            $stmt->bindParam(1, $card[0]);  //占位符的位置从1开始
            $stmt->bindParam(2, $card[1]);
            $stmt->execute();               //执行预处理
             */
            //方法二:
            /*
            $stmt->bindValue(1, $card[0]);
            $stmt->bindValue(2, $card[1]);
            $stmt->execute();
             */
            //方法三:如果占位符的顺序和数组的顺序一致,可以直接传递数组
            $stmt->execute($card);  
        }
        echo '数据处理完成';
    ?>
    
    # 参数占位符
    <?php
        $dsn= 'mysql:host=localhost;port=3306;dbname=sel;charset=utf8';
        $pdo= new PDO($dsn,'root','');
        //创建预处理对象
        $stmt=$pdo->prepare("insert into bank values (:p1,:p2)");   //:p1,:p2是参数占位符
        //执行预处理
        $cards=[
            ['p1'=>'1005','p2'=>500],
            ['p1'=>'1006','p2'=>1000]
        ];
        foreach($cards as $card){
            //方法一:
            /*
            $stmt->bindParam(':p1', $card['p1']);
            $stmt->bindParam(':p2', $card['p2']);
            $stmt->execute();
            */
            //方法二:但数组的下标和参数名一致的时候就可以直接传递关联数组
            $stmt->execute($card);
        }
        echo '数据处理完成';
    ?>
    

    PDO异常处理

    • 概念
      • PDOException是PDO的异常类
      • 实例化PDO会自动抛出异常
      • 其他操作不会抛出异常,需要设置PDO的异常模式
      • PDO异常模式
        • PDO::ERRMODE_EXCEPTION 抛出异常
        • PDO::ERRMODE_SILENT 中断
        • PDO::ERRMODE_WARNING 警告
    <?php
    try{
        $dsn='mysql:dbname=data;charset=utf8';
        $pdo=new PDO($dsn,'root','');
        //这是PDO错误模式属性,PDO自动抛出异常
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->query('select * from newsssssss');  //自动抛出异常
    } catch (PDOException $ex) {
        echo '错误信息:'.$ex->getMessage(),'<br>';
        echo '错误文件:'.$ex->getFile(),'<br>';
        echo '错误行号:'.$ex->getLine();
    }
    ?>
    

    单例模式封装MySQL-PDO

    • 分析
      • 单例模式
      • 初始化参数
      • 连接数据库
      • 执行增删改
      • 执行查询
        • 返回二维数组
        • 返回一维数组
        • 返回一行一列

    第一部分:单例、初始化参数、实例化PDO

    <?php
    class MyPDO{
        private $type;      //数据库类别
        private $host;      //主机地址
        private $port;      //端口号
        private $dbname;    //数据库名
        private $charset;   //字符集
        private $user;      //用户名
        private $pwd;       //密码
        private $pdo;       //保存PDO对象
        private static $instance;
        private function __construct($param) {
            $this->initParam($param);
            $this->initPDO();
        }
        private function __clone() {
        }
        public static function getInstance($param=array()){
            if(!self::$instance instanceof self)
                self::$instance=new self($param);
            return self::$instance;
        }
        //初始化参数
        private function initParam($param){
            $this->type=$param['type']??'mysql';
            $this->host=$param['host']??'127.0.0.1';
            $this->port=$param['port']??'3306';
            $this->dbname=$param['dbname']??'data';
            $this->charset=$param['charset']??'utf8';
            $this->user=$param['user']??'root';
            $this->pwd=$param['pwd']??'root';
        }
        //初始化PDO
        private function initPDO(){
            try{
                $dsn="{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
                $this->pdo=new PDO($dsn, $this->user, $this->pwd);
            } catch (PDOException $ex) {
                echo '错误编号:'.$ex->getCode(),'<br>';
                echo '错误行号:'.$ex->getLine(),'<br>';
                echo '错误文件:'.$ex->getFile(),'<br>';
                echo '错误信息:'.$ex->getMessage(),'<br>';
                exit;
            }
        }
    }
    //测试
    $param=array(
    );
    $mypdo= MyPDO::getInstance($param);
    var_dump($mypdo);
    ?>
    

    第二部分:数据操作部分

    <?php
    class MyPDO{
        private $type;      //数据库类别
        private $host;      //主机地址
        private $port;      //端口号
        private $dbname;    //数据库名
        private $charset;   //字符集
        private $user;      //用户名
        private $pwd;       //密码
        private $pdo;       //保存PDO对象
        private static $instance;
        private function __construct($param) {
            $this->initParam($param);
            $this->initPDO();
            $this->initException();
        }
        private function __clone() {
        }
        public static function getInstance($param=array()){
            if(!self::$instance instanceof self)
                self::$instance=new self($param);
            return self::$instance;
        }
        //初始化参数
        private function initParam($param){
            $this->type=$param['type']??'mysql';
            $this->host=$param['host']??'127.0.0.1';
            $this->port=$param['port']??'3306';
            $this->dbname=$param['dbname']??'data';
            $this->charset=$param['charset']??'utf8';
            $this->user=$param['user']??'root';
            $this->pwd=$param['pwd']??'root';
        }
        //初始化PDO
        private function initPDO(){
            try{
                $dsn="{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
                $this->pdo=new PDO($dsn, $this->user, $this->pwd);
            } catch (PDOException $ex) {
                $this->showException($ex);
                exit;
            }
        }
        
        //显示异常
        private function showException($ex,$sql=''){
            if($sql!=''){
                echo 'SQL语句执行失败<br>';
                echo '错误的SQL语句是:'.$sql,'<br>';
            }
            echo '错误编号:'.$ex->getCode(),'<br>';
            echo '错误行号:'.$ex->getLine(),'<br>';
            echo '错误文件:'.$ex->getFile(),'<br>';
            echo '错误信息:'.$ex->getMessage(),'<br>';
        }
        //设置异常模式
        private function initException(){
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
        }
    
        //执行增、删、改操作
        public function exec($sql){
            try{
                return $this->pdo->exec($sql);
            } catch (PDOException $ex) {
                $this->showException($ex, $sql);
                exit;
            }
        }
        //获取自动增长的编号
        public function lastInsertId(){
            return $this->pdo->lastInsertId();
        }
    }
    //测试
    $param=array(
       
    );
    $mypdo= MyPDO::getInstance($param);
    //echo $mypdo->exec('delete from news where id=6');
    if($mypdo->exec("insert into news values (null,'11','1111',unix_timestamp())"))
        echo '自动增长的编号是:'.$mypdo->lastInsertId ();
    ?>
    

    第三部分:数据查询部分

    <?php
    class MyPDO{
       ...
        
        //判断匹配的类型
        private function fetchType($type){
            switch ($type){
                case 'num':
                    return PDO::FETCH_NUM;
                case 'both':
                    return PDO::FETCH_BOTH;
                case 'obj':
                    return PDO::FETCH_OBJ;
                default:
                     return PDO::FETCH_ASSOC;
            }
        }
        //获取所有数据 ,返回二维数组
        public function fetchAll($sql,$type='assoc'){
            try{
                $stmt=$this->pdo->query($sql);  //获取PDOStatement对象
                $type= $this->fetchType($type); //获取匹配方法
                return $stmt->fetchAll($type);
            } catch (Exception $ex) {
                $this->showException($ex, $sql);
            }
        }
        //获取一维数组
        public function fetchRow($sql,$type='assoc'){
            try{
                $stmt=$this->pdo->query($sql);  //获取PDOStatement对象
                $type= $this->fetchType($type); //获取匹配方法
                return $stmt->fetch($type);
            } catch (Exception $ex) {
                $this->showException($ex, $sql);
                exit;
            }
        }
        //返回一行一列
        public function fetchColumn($sql){
            try{
                 $stmt=$this->pdo->query($sql);
                return $stmt->fetchColumn();
            } catch (Exception $ex) {
                $this->showException($ex, $sql);
                exit;
            }
            
        }
        
    }
    //测试
    $param=array(
       
    );
    $mypdo= MyPDO::getInstance($param);
    //echo $mypdo->exec('delete from news where id=6');
    /*
    if($mypdo->exec("insert into news values (null,'11','1111',unix_timestamp())"))
        echo '自动增长的编号是:'.$mypdo->lastInsertId ();
     */
    
    //$list=$mypdo->fetchAll('select * from news');
    //$list=$mypdo->fetchRow('select * from news where id=1');
    $list=$mypdo->fetchColumn('select count(*) from news');
    echo '<pre>';
    var_dump($list);
    ?>
    
  • 相关阅读:
    第二次作业
    初学JAVA的 感想 尹鑫磊
    初学JAVA 感想
    《将博客搬至CSDN》
    JAVA中的几种内部类
    JAVA-静态变量与实体变量
    teacher页面的代码
    测试说明书的概述和摘要
    网站的概述
    html与xhtml的区别
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/14138085.html
Copyright © 2011-2022 走看看