PDO参数、方法大全
PDO::PARAM_BOOL 表示一个布尔类型
PDO::PARAM_NULL 表示一个SQL中的NULL类型
PDO::PARAM_INT 表示一个SQL中的INTEGER类型
PDO::PARAM_STR 表示一个SQL中的SQL CHAR,VARCHAR类型
PDO::PARAM_LOB 表示一个SQL中的large object类型
PDO::PARAM_STMT 表示一个SQL中的recordset类型,还没有被支持
PDO::PARAM_INPUT_OUTPUT
Specifies that the parameter is an INOUT parameter for a stored procedure. You must
bitwise-OR this value with an explicit PDO::PARAM_* data type.
PDO::FETCH_LAZY 将每一行结果作为一个对象返回
PDO::FETCH_ASSOC 仅仅返回以键值作为下标的查询的结果集,名称相同的数据只返回一个
PDO::FETCH_NAMED 仅仅返回以键值作为下标的查询的结果集,名称相同的数据以数组形式返回
PDO::FETCH_NUM 仅仅返回以数字作为下标的查询的结果集
PDO::FETCH_BOTH 同时返回以键值和数字作为下标的查询的结果集
PDO::FETCH_OBJ 以对象的形式返回结果集
PDO::FETCH_BOUND
将PDOStatement::bindParam()和PDOStatement::bindColumn()所绑定的值作为变量名赋值后返回
PDO::FETCH_COLUMN 表示仅仅返回结果集中的某一列
PDO::FETCH_CLASS 表示以类的形式返回结果集
PDO::FETCH_INTO 表示将数据合并入一个存在的类中进行返回
PDO::FETCH_FUNC
PDO::FETCH_GROUP
PDO::FETCH_UNIQUE
PDO::FETCH_KEY_PAIR 以首个键值下表,后面数字下表的形式返回结果集
PDO::FETCH_CLASSTYPE
PDO::FETCH_SERIALIZE 表示将数据合并入一个存在的类中并序列化返回
PDO::FETCH_PROPS_LATE
Available since PHP 5.2.0
PDO::ATTR_AUTOCOMMIT 在设置成 true的时候,PDO 会自动尝试停止接受委托,开始执行
PDO::ATTR_PREFETCH 设置应用程序提前获取的数据大小,并非所有的数据库哦度支持
PDO::ATTR_TIMEOUT 设置连接数据库超时的值
PDO::ATTR_ERRMODE 设置 Error 处理的模式
PDO::ATTR_SERVER_VERSION 只读属性,表示PDO 连接的服务器端数据库版本
PDO::ATTR_CLIENT_VERSION 只读属性,表示PDO 连接的客户端PDO 驱动版本
PDO::ATTR_SERVER_INFO 只读属性,表示PDO 连接的服务器的meta 信息
PDO::ATTR_CONNECTION_STATUS
PDO::ATTR_CASE 通过 PDO::CASE_*中的内容对列的形式进行操作
PDO::ATTR_CURSOR_NAME 获取或者设定指针的名称
PDO::ATTR_CURSOR 设置指针的类型, PDO 现在支持PDO::CURSOR_FWDONLY 和
PDO::CURSOR_FWDONLY
PDO::ATTR_DRIVER_NAME 返回使用的PDO驱动的名称
PDO::ATTR_ORACLE_NULLS 将返回的空字符串转换为SQL的NULL
PDO::ATTR_PERSISTENT 获取一个存在的连接
PDO::ATTR_STATEMENT_CLASS
PDO::ATTR_FETCH_CATALOG_NAMES 在返回的结果集中,使用自定义目录名称来代替字段名。
PDO::ATTR_FETCH_TABLE_NAMES 在返回的结果集中,使用自定义表格名称来代替字段名。
PDO::ATTR_STRINGIFY_FETCHES
PDO::ATTR_MAX_COLUMN_LEN
PDO::ATTR_DEFAULT_FETCH_MODE
Available since PHP 5.2.0
PDO::ATTR_EMULATE_PREPARES
Available since PHP 5.1.3.
PDO::ERRMODE_SILENT 发生错误时不汇报任何的错误信息,是默认值
PDO::ERRMODE_WARNING 发生错误时发出一条php的E_WARNING 的信息
PDO::ERRMODE_EXCEPTION 发生错误时抛出一个PDOException
PDO::CASE_NATURAL 回复列的默认显示格式
PDO::CASE_LOWER 强制列的名字小写
PDO::CASE_UPPER 强制列的名字大写
PDO::NULL_NATURAL
PDO::NULL_EMPTY_STRING
PDO::NULL_TO_STRING
PDO::FETCH_ORI_NEXT 获取结果集中的下一行数据,仅在有指针功能时有效
PDO::FETCH_ORI_PRIOR 获取结果集中的上一行数据,仅在有指针功能时有效
PDO::FETCH_ORI_FIRST 获取结果集中的第一行数据,仅在有指针功能时有效
PDO::FETCH_ORI_LAST 获取结果集中的最后一行数据,仅在有指针功能时有效
PDO::FETCH_ORI_ABS 获取结果集中的某一行数据,仅在有指针功能时有效
PDO::FETCH_ORI_REL 获取结果集中当前行后某行的数据,仅在有指针功能时有效
PDO::CURSOR_FWDONLY 建立一个只能向后的指针操作对象
PDO::CURSOR_SCROLL 建立一个指针操作对象,传递PDO::FETCH_ORI_*中的内容来控制结果集
PDO::ERR_NONE (string) 设定没有错误时候的错误信息
PDO常用方法详解
PDO 是一个“数据库访问抽象层”,作用是统一各种数据库(MySQL、MSSQL、Oracle、DB2、PostgreSQL……)的访问接口,能轻松的在不同的数据库之间完成切换,使得数据库间的移植容易实现。
开启PDO
在pho.ini中查找php_pdo_yourssqlserverhere.extis把注释去掉就行了,很多集成环境默认是开启的。
可以用class_exitsts(“PDO”); 等方法调试是否开启
PDO对象建立
$dsn = 'mysql:host=localhost;dbname=my_db;port=3306'; //数据源:host主机名称、dbname数据库名称、port:数据库端口 $username = 'root'; //数据库用户名 $password = 'root'; //数据库密码 $pdo = new PDO($dsn, $username, $password);
转义用户输入(的特殊字符)
你可曾听说过(mysqli_)real_escape_string,这是用于确保用户输入安全数据。PDO提供了一个方法叫做quote,这个方法可以把输入字符串中带有引号的地方进行特殊字符转义。
$pdo->quote($input);
预处理语句
尽管exec方法和查询在PHP中仍然被大量使用和支持,但是PHP官网上还是要求大家用预处理语句的方式来替代。为什么呢?主要是因为:它更安全。预处理语句不会直接在实际查询中插入参数,这就避免了许多潜在的SQL注入。
然而出于某种原因,PDO实际上并没有真正的使用预处理,它是在模拟预处理方式,在将语句传给SQL服务器之前会把参数数据插入到语句中,这使得某些系统容易受到SQL注入。
如果你的SQL服务器不真正的支持预处理,我们可以很容易的通过如下方式在PDO初始化时传参来修复这个问题:
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
接下来开始我们的第一个预处理语句吧:
$statement = $pdo->prepare('SELECT * FROM test WHERE id=? AND username=?'); $statement = $pdo->prepare('SELECT * FROM test WHERE id=:id AND username=:username');
正如你所见,有两种创建参数的方法,命名(id=:id)的与匿名的(id=?)(不可以同时出现在一个语句中)。然后你可以使用bindValue来敲进你的输入:
$statement->bindValue(1, $id); $statement->bindValue(2, $username); $statement->bindValue(':id', $id); $statement->bindValue(':username', $username);
注意使用命名参数的时候你要包含进冒号(:)。PDO还有一个bindParam方法,可以通过引用绑定数值,也就是说它只在语句执行的时候查找相应数值。
bindParam() 和 bindValue() 非常相似。
唯一的区别就是前者使用一个PHP变量绑定参数,而后者使用一个值。
所以使用bindParam是第二个参数只能用变量名,而不能用变量值,而bindValue至可以使用具体值。
$stm = $pdo->prepare("select * from users where user = :user"); $user = "jack"; //正确 $stm->bindParam(":user",$user); //错误 //$stm->bindParam(":user","jack"); //正确 $stm->bindValue(":user",$user); //正确 $stm->bindValue(":user","jack");
另外在存储过程中,bindParam可以绑定为input/output变量,如下面
$stm = $pdo->prepare("call func(:param1)"); $param1 = "abcd"; $stm->bindParam(":param1",$param1); //正确 $stm->execute();
存储过程执行过后的结果可以直接反应到变量上。
对于那些内存中的大数据块参数,处于性能的考虑,应优先使用前者。
为了避免只使用bindValue带来的代码碎片,你可以用数组给execute方法作为参数,像这样:
$statement->execute(array(1=>$id, 2=>$username)); $statement->execute(array(':id'=>$id, ':username'=>$username));
绑定值到变量 详情看官方文档http://php.net/manual/zh/pdostatement.bindcolumn.php
绑定结果集中的列到PHP变量是一种使每行包含的数据在应用程序中立即可用的有效方法。下面的例子演示了 PDO 怎样用多种选项和缺省值绑定和检索列。
<?php function readData($dbh) { $sql = 'SELECT name, colour, calories FROM fruit'; try { $stmt = $dbh->prepare($sql); $stmt->execute(); /* 通过列号绑定 */ $stmt->bindColumn(1, $name); $stmt->bindColumn(2, $colour); /* 通过列名绑定 */ $stmt->bindColumn('calories', $cals); while ($row = $stmt->fetch(PDO::FETCH_BOUND)) { $data = $name . "\t" . $colour . "\t" . $cals . "\n"; print $data; } } catch (PDOException $e) { print $e->getMessage(); } } readData($dbh); ?>
事务
一个事务就是执行一组查询,但是并不保存他们的影响到数据库中。这样做的好处是如果你执行了4条相互依赖的插入语句,当有一条失败后,你可以回滚使得其他的数据不能够插入到数据库中,确保相互依赖的字段能够正确的插入。你需要确保你使用的数据库引擎支持事务。
开启事务
你可以很简单的使用beginTransaction()方法开启一个事务:
$pdo->beginTransaction(); $pdo->inTransaction(); // true! $pdo->query('SELECT * .....'); .......
然后你可以继续执行你的数据库操作语句,在最后提交事务:
$db->commit();
还有类似MySQLi中的rollBack()方法,但是它并不是回滚所有的类型(例如在MySQL中使用DROP TABLE),这个方法并不是真正的可靠,我建议尽量避免依赖此方法。
其他有用的选项
有几个选项你可以考虑用一下。这些可以作为你的对象初始化时候的第四个参数输入。
$options = array($option1 => $value1, $option[..]); $db = new PDO($dsn, $username, $password, $options); PDO::ATTR_DEFAULT_FETCH_MODE
你可以选择PDO将返回的是什么类型的结果集,如PDO::FETCH_ASSOC,会允许你使用result[‘columnname‘],或者PDO::FETCHOBJ,会返回一个匿名对象,以便你使用result[‘columnname‘],或者PDO::FETCHOBJ,会返回一个匿名对象,以便你使用result->column_name
你还可以将结果放入一个特定的类(模型),可以通过给每一个单独的查询设置一个读取模式,就像这样:
$query = $db->query(‘SELECT * FROM `foods`‘); $foods = $query->fetchAll(PDO::FETCH_CLASS, ‘Food‘); PDO::ATTR_ERRMODE
所有读取模式
上面我们已经解释过这一条了,但喜欢TryCatch的人需要用到:PDO::ERRMODE_EXCEPTION。如果不论什么原因你想抛出PHP警告,就使用PDO::ERRMODE_WARNING。
PDO::ATTR_TIMEOUT
当你为载入时间而着急时,你可以使用此属性来为你的查询指定一个超时时间,单位是秒. 注意,如果超过你设置的时间,缺省会抛出E_WARNING异常, 除非 PDO::ATTR_ERRMODE 被改变.
更多属性信息可以在 PHP官网的属性设置 里查看到.
最后的思考
PDO是一个在PHP中访问你的数据库的很棒的方式,可以认为是最好的方式。除非你拒绝使用面向对象的方法或是太习惯 MySQLi 的方法名称,否则没有理由不使用PDO。
更好的是完全切换到只使用预处理语句,这最终将使你的生活更轻松!
PDO常用方法:
- PDO::query()主要用于有记录结果返回的操作(PDOStatement),特别是select操作。
- PDO::exec()主要是针对没有结果集合返回的操作。如insert,update等操作。返回影响行数。
- PDO::lastInsertId()返回上次插入操作最后一条ID,但要注意:如果用insert into tb(col1,col2) values(v1,v2),(v11,v22)..的方式一次插入多条记录,lastinsertid()返回的只是第一条(v1,v2)插入时的ID,而不是最后一条记录插入的记录ID。
- PDOStatement::fetch()是用来获取一条记录。配合while来遍历。
- PDOStatement::fetchAll()是获取所有记录集到一个中。
- PDOStatement::fetchcolumn([int column_indexnum])用于直接访问列,参数column_indexnum是该列在行中的从0开始- 索引值,但是,这个方法一次只能取得同一行的一列,只要执行一次,就跳到下一行。因此,用于直接访问某一列时较好用,但要遍历多列就用不上。
- PDOStatement::rowcount()适用于当用query(“select …”)方法时,获取记录的条数。也可以用于预处理中。$stmt->rowcount();
- PDOStatement::columncount()适用于当用query(“select …”)方法时,获取记录的列数,不适用于预处理。
注解:
1、选fetch还是fetchall?
小记录集时,用fetchall效率高,减少从数据库检索次数,但对于大结果集,用fetchall则给系统带来很大负担。数据库要向WEB前端传输量太大反而效率低。
2、fetch()或fetchall()有几个参数:
mixed pdostatement::fetch([int fetch_style [,int cursor_orientation [,int cursor_offset]]])
array pdostatement::fetchAll(int fetch_style)
fetch_style参数:
■row=row=rs->fetchAll(PDO::FETCH_BOTH); FETCH_BOTH是默认的,可省,返回关联和索引。
■row=row=rs->fetchAll(PDO::FETCH_ASSOC); FETCH_ASSOC参数决定返回的只有关联数组。
■row=row=rs->fetchAll(PDO::FETCH_NUM); 返回索引数组
■row=row=rs->fetchAll(PDO::FETCH_OBJ); 如果fetch()则返回对象,如果是fetchall(),返回由对象组成的二维数组
fetchAll实例
$sql = 'SELECT * FROM test WHERE id=?'; $stmt = $pdo->prepare($sql); $stmt->execute(array(1=>$id)); foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $row){ echo $row['username'].$row['password']; }
fetch实例
$sql = 'SELECT * FROM test WHERE id=?'; $stmt = $pdo->prepare($sql); $stmt->execute(array(1=>$id)); while($row = $stmt->fetch(PDO::FETCH_ASSOC)){ echo $row['username'].$row['password']; }
fetch每执行一次记录都往下移动一次,所以用while循环遍历结果集。