PDO预处理

来源:互联网 发布:java架构师书籍知乎 编辑:程序博客网 时间:2024/05/22 05:04

PDOStatement类

   该类有一个语句,和PDO中对象的exec()及query()相比,可以帮助处理结果集
   预处理的好处是,只在服务端编辑一次SQL语句,可以大大提高效率,同时在安全上可以防止sql注入。传统的防注入的方法是屏蔽表单中的空格或者屏蔽掉sql注入语句中的符号,如*等。
  所以好的严谨的程序一般不用exec()和query()

<?php
    try{
           $pdo=new PDO("mysql:host=localhost;dbname=xsphpdb","root","");
    }catch(PDOException $e){
           echo $e->getMessage();
    }
    //$pdo->exec();//传统用法  负责 更新,删除,插入
    //$pdo->query();//传统用法 负责 查询
    //$stmt=$pdo->prepare("update shops set name='a' where id=100");//prepare这种是把上述两种方法合起来了,负责所有的
    $stmt=$pdo->prepare("insert into shops(name,price,num,desn) values(?,?,?,?)");//?相当于操作索引数组,是按所引顺序找的点位符
    //准备好下面的一条语句,并入到服务器端,也已经编译过来了,就差为它分配数据过来
    //$stmt=$pdo->prepare("insert into shops(name,price,num,desn) values(:name,:price,:num,:desn)");//名字参数相当于操作关联数组
   //下面是绑定参数

    $stmt->bindParam(1,$name);
    $stmt->bindParam(3,$num);
    $stmt->bindParam(4,$desn);
    $stmt->bindParam(2,$p);

    $name="wwww1";
    $num=101;
    $desn="heool1";
    $p=34.51;
    if($stmt->execute()){
        echo "执行成功!";
        echo "最后插入的ID:".$pdo->lastInsertId();
    }else{
        echo "执行失败!";
    }

PDO对预处理语句的支持需要使用PDOStatement类对象,但该类对象并不是通过NEW关键字实例化出来的,而是通过PDO对象中的prepare()方法,在数据库服务器中准备好一个预处理的SQL语句后直接返回的。如果通过之前执行PDO对象中的query()方法返回的PDOStatement类对象,只代表的是一个结果集对象。而如果通过执行PDO对象中的prepare()方法产生的PDOStatement类对象,则为一个查询对象,能定义和执行参数化的SQL命令。PDOStatement类中的全部成员方法如下所示:

01.PDOStatement::bindColumn ― 绑定一列到一个 PHP 变量
02. 
03.PDOStatement::bindParam ― 绑定一个参数到指定的变量名
04. 
05.PDOStatement::bindValue ― 把一个值绑定到一个参数
06. 
07.PDOStatement::closeCursor ― 关闭游标,使语句能再次被执行。
08. 
09.PDOStatement::columnCount ― 返回结果集中的列数
10. 
11.PDOStatement::debugDumpParams ― 打印一条 SQL 预处理命令
12. 
13.PDOStatement::errorCode ― 获取跟上一次语句句柄操作相关的 SQLSTATE
14. 
15.PDOStatement::errorInfo ― 获取跟上一次语句句柄操作相关的扩展错误信息
16. 
17.PDOStatement::execute ― 执行一条预处理语句
18. 
19.PDOStatement::fetch ― 从结果集中获取下一行
20. 
21.PDOStatement::fetchAll ― 返回一个包含结果集中所有行的数组
22. 
23.PDOStatement::fetchColumn ― 从结果集中的下一行返回单独的一列。
24. 
25.PDOStatement::fetchObject ― 获取下一行并作为一个对象返回。
26. 
27.PDOStatement::getAttribute ― 检索一个语句属性
28. 
29.PDOStatement::getColumnMeta ― 返回结果集中一列的元数据
30. 
31.PDOStatement::nextRowset ― 在一个多行集语句句柄中推进到下一个行集
32. 
33.PDOStatement::rowCount ― 返回受上一个 SQL 语句影响的行数
34. 
35.PDOStatement::setAttribute ― 设置一个语句属性
36. 
37.PDOStatement::setFetchMode ― 为语句设置默认的获取模式。
 
使用命名参数作为占位符的INSERT插入语句:
$dbh->prepare(“insert into contactinfo(name,address,phone) values(:name,:address,:phone)”);
 
使用问号(?)参数作为占位符的INSERT插入语句:
$dbh->prepare(“insert into contactinfo(name,address,phone) values(?,?,?)”);

什么是预处理?

成熟的数据库都支持预处理语句(Prepared Statements)的概念。

它们是什么东西?你可以把它们想成是一种编译过的要执行的SQL语句模板,可以使用不同的变量参数定制它。

预处理语句具有两个主要的优点:

1 查询只需要被解析(或准备)一次,但可以使用相同或不同的参数执行多次。当查询准备好(Prepared)之后,数据库就会分析,编译并优化它要执行查询的计划。

对于复杂查询来说,如果你要重复执行许多次有不同参数的但结构相同的查询,这个过程会占用大量的时间,使得你的应用变慢。

通过使用一个预处理语句你就可以避免重复分析、编译、优化的环节。简单来说,预处理语句使用更少的资源,执行速度也就更快。

2 传给预处理语句的参数不需要使用引号,底层驱动会为你处理这个。

如果你的应用独占地使用预处理语句,你就可以确信没有SQL注入会发生。

代码演示:

<?phpheader('content-type:text/html; charset=utf-8');//实例化pdo对象$pdo = new PDO('mysql:host=127.0.0.1;port=3306;dbname=test;', 'root', '888888');//通过query函数执行sql命令$pdo->query('set names utf8');//插入数据$sql    = "insert into persons (name,age) values (?, ?);";$preObj = $pdo->prepare($sql);$res    = $preObj->execute(array('小明', 22));var_dump($res);//删除数据$sql = "delete from persons where id = ?";$preObj = $pdo->prepare($sql);$res    = $preObj->execute(array(3));var_dump($res);//修改数据$sql = "update persons set name = ? where id = ?;";$preObj = $pdo->prepare($sql);$res    = $preObj->execute(array('lucy', 5));var_dump($res);//查询数据$sql = "select * from persons where age > ? order by id desc;";$preObj = $pdo->prepare($sql);$preObj->execute(array(20));$arr = $preObj->fetchAll(PDO::FETCH_ASSOC);/* * FETCH_BOTH      是默认的,可省,返回关联和索引。 * FETCH_ASSOC     参数决定返回的只有关联数组。 * PDO::FETCH_NUM  返回索引数组 * PDO::FETCH_OBJ  返回由对象组成的二维数组 */print_r($arr);

 PDOStatement类:准备语句,处理结果集    也就是预处理,安全,高效,推荐使用

    两种占位符号:?参数         索引数组,按索引顺序使用                 名子参数      关联数组,按名称使用,和顺序无关,以冒号开头,自己定义

    $stmt=$pdo->prepare($sql);     $sql可是是任意sql语句,这与mysqli不同

两种点位符号

<?php  try{    $pdo=new PDO("mysql:host=localhost;dbname=mysqldb","root","snail");  }catch(PDOException $e){    echo $e->getMessage();  }

  //准备一条语句,并放到服务器端,而且编译  $stmt=$pdo->prepare("insert into shop(name,price)values(?,?)");//  $stmt=$pdo->prepare("insert into shop(name,price)values(:na,:pr)");

  //绑定参数(变量和参数绑定)  $stmt->bindparam(1,$name);  $stmt->bindparam(2,$price);

//  $stmt->bindparam(":na",$name);//  $stmt->bindparam(":pr",$price);

  $name="liwu11";  $price=234.4311;

  if($stmt->execute()){    echo "执行成功";    echo "最后插入的ID:".$pdo->lastInsertId();  }else{    echo "执行失败";  }?>

<?php//以数组方式向服务器传值 

 try{    $pdo=new PDO("mysql:host=localhost;dbname=mysqldb","root","snail");  }catch(PDOException $e){    echo $e->getMessage();  }

  $stmt=$pdo->prepare("select * from shop where id >:id");

  $stmt->execute(array(':id'=>130));

  $row=$stmt->fetch();  print_r($row);  echo '<br>';?>

<?php

//用fetch(),fetchAll()来获取查询结果  try{    $pdo=new PDO("mysql:host=localhost;dbname=mysqldb","root","snail");  }catch(PDOException $e){    echo $e->getMessage();  }

  $stmt=$pdo->prepare("select * from shop where id >:id");

  $stmt->execute(array(':id'=>130));

/*  单条获取fetch()   $stmt->setFetchMode(PDO::FETCH_ASSOC);  //设置获取模式  while($row=$stmt->fetch()){    print_r($row);    echo '<br>';  }*/

  //多条获取fetchAll()//  $stmt->setFetchMode(PDO::FETCH_ASSOC);  $data=$stmt->fetchAll(PDO::FETCH_ASSOC);  //也可以用上句进行设置  echo '<pre>';  print_r($data);  echo '</pre>';?>

<?php//以表格输出查询结果 

try{    $pdo=new PDO("mysql:host=localhost;dbname=mysqldb","root","snail");  }catch(PDOException $e){    echo $e->getMessage();  }

  $stmt=$pdo->prepare("select id,name,price from shop where id >:id");

  $stmt->execute(array(':id'=>130));

  $stmt->bindColumn(id,$id);  $stmt->bindColumn(name,$name);  $stmt->bindColumn(price,$price);

  echo '<table border=1 align="center" width=800px>';  echo '<tr>';  for($i=0;$i<$stmt->columncount();$i++){    $field=$stmt->getColumnMeta($i);    echo '<th>'.$field["name"].'</th>';  }  echo "</tr>";

  while($stmt->fetch()){    echo '<tr>';    echo '<td>'.$id.'</td>';    echo '<td>'.$name.'</td>';    echo '<td>'.$price.'</td>';    echo '</tr>';  }

  echo '</table>';

  echo "行:".$stmt->rowcount()."<br>";  echo "列:".$stmt->columncount()."<br>";

?>


0 0