通过上一节内容 php pdo 简单使用(一)了解了链接的创建和简单的操作。
通过 pdo 有三种方式执行sql语句: exec, query, prepared statement
1. exec() 函数适用于执行一次sql 操作,并且不适用于select语句 参见:http://php.net/manual/zh/pdo.exec.php
2. query() 函数适用于执行一次sql操作,并且在下一次query之前要fetch 出所有的结果否则执行将会失败 参见:http://php.net/manual/zh/pdo.query.php
3. 如果一类查询(查询结构相似而具体的参数不一)需要一次解析而执行使用很多次,可以先用prepared statement,这样可以为具体的查询的执行做好准备,避免了分析、编译、优化的循环,将减少资源占用率,从而提高运行效率。通过对数据库进行prepare操作,便会返回PDOStatement数据类型,从而在其基础上展开execute、fetch等进一步的操作。
使用prepared statement还可以防止SQL注入。查询语句里可以使用包含命名(:name)和问号(?)的参数占位符,分别将用associated array 和indexed array传入数值。
代码示例:
<?php
header("Content-type: text/html; charset=utf-8");
$dbType = ‘mysql‘;
$dbUser = ‘root‘;
$dbPass = ‘simael‘;
$dbhost = ‘localhost‘;
$dbName = ‘pdotest‘;
$dsn="$dbType:host=$dbhost;dbname=$dbName";
try{
$pdo = new PDO($dsn, $dbUser, $dbPass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES ‘utf8‘;"));
echo "PDO成功连接MySQL数据库!<br>";
}catch(PDOException $exception){
echo $exception->getMessage();
}
$pdo->query(‘set names utf8‘);
$name = ‘‘;
$text = ‘‘;
// 用问号占位符传入参数
$stmt = $pdo->prepare("INSERT INTO users (name, text) VALUES (?, ?)");
//$stmt->bindParam(1, $name); // 这里只能传入变量,不能是常量例如 $stmt->bindParam(1, ‘simael‘); 报错
//$stmt->bindParam(2, $text);
$stmt->bindValue(1, ‘bindValue‘);
$stmt->bindValue(2, ‘bindValue \‘s text‘);
$name = ‘again name‘;
$text = ‘again text text‘;
$stmt->execute();
//$stmt->execute(array(‘mike‘,‘mike text‘));
// 用命名占位符传入参数
$stmt2 = $pdo->prepare("SELECT * FROM users WHERE name like :name");
//$stmt2->bindParam(‘:name‘,$name);
$stmt2->execute(array(‘:name‘=>‘%mike%‘));
/*while($row = $stmt2->fetch(PDO::FETCH_ASSOC)){
print_r($row);
echo ‘<br>‘;
}*/
//print_r($stmt2->fetchAll(PDO::FETCH_BOTH));
//print_r($stmt2->fetchAll(PDO::FETCH_ASSOC));
print_r($stmt2->fetchAll(PDO::FETCH_OBJ));
注意注释的代码,都可以测试一下。
例如,我们使用问号占位符,通过bindParam()函数传入参数的时候,第二个参数必须是变量,想使用常量应当使用函数bindValue()
参见:
http://php.net/manual/zh/pdostatement.bindparam.php
http://php.net/manual/en/pdostatement.bindvalue.php
当然我们也可以直接在 execute()函数中直接传入参数。
上面的例子还包含了使用Pdo 的插入和查询操作,其它操作类似。
最后打印结果有多种方式:
$row=$dbh->fetchAll(PDO::FETCH_BOTH); //FETCH_BOTH是默认的,可省,返回关联和索引。
$row=$dbh->fetchAll(PDO::FETCH_ASSOC); //FETCH_ASSOC参数决定返回的只有关联数组。
$row=$dbh->fetchAll(PDO::FETCH_NUM); //返回索引数组
$row=$dbh->fetchAll(PDO::FETCH_OBJ); //如果fetch()则返回对象,如果是fetchall(),返回由对象组成的二维数组
错误处理:
静默模式(默认模式)
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT); //不显示错误
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);//显示警告错误,并继续执行
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);//产生致命错误,PDOException
事务:
try{
$dbh->beginTransaction();
$dbh->exec("Insert INTO `test`.`table` (`name` ,`text`)VALUES (‘mick‘, ‘text1‘);");
$dbh->exec("Insert INTO `test`.`table` (`name` ,`text`)VALUES (‘lily‘, ‘text2‘);");
$dbh->exec("Insert INTO `test`.`table` (`name` ,`text`)VALUES (‘susan‘, ‘text3‘);");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
使用pdo 建立一个持久连接:
<?php
$db = new PDO(‘mysql:host=localhost;dbname=testpdo‘, $user, $pass, array(
PDO::ATTR_PERSISTENT => true
));
?>
持久的连接能够跨越代码,在一个代码执行完毕时并未被关闭,而是被缓存起来,
以供另一段拥有同样权限的代码重复使用。这样便不必每次都新建一个连接,省了不少事不说,还能够加快网站速度。