企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] **** ## 1 PDO的意义 PDO(php data object)**PHP数据对象扩展**为数据库定义了一个轻量级的一致接口。 PDO扩展自身并不能实现任何数据库功能,必须使用**具体数据库的PDO驱动**来访问数据库服务,实现PDO接口的每个数据库驱动可以将特定数据库的访问作为标准扩展功能。 PDO提供了一个**数据访问**抽象层,意味着不管使用哪种数据库,都可以使用相同的函数来查询和获取数据。通常用用作实现数据库访问的底层。 在PHP5.0中PDO是作为一个扩展使用,在PHP5.1后开始附带PDO扩展。 ## 2 PDO的使用 ### 2-1 PDO连接数据库 >[info] 1 可以通过创建PDO基类的实例来连接数据库。构造函数接受用于指定数据库源以及用户名和密码等参数 ~~~ ;PDO数据库连接 $dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass ); ~~~ >[info] 2 可以使用PDOException处理连接错误。 ~~~ ;PDO数据连接异常处理 try { $dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass ); foreach( $dbh -> query ( 'SELECT * from FOO' ) as $row ) { print_r ( $row ); } $dbh = null ; } catch ( PDOException $e ) { print "Error!: " . $e -> getMessage () . "<br/>" ; die(); } ~~~ >[info] 3 构造函数中可以携带不同参数实现不同的连接,下面使用参数实现持久化连接 ~~~ ;使用PDO参数实现持久化连接 $dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass , array( PDO :: ATTR_PERSISTENT => true )); ~~~ >[info] 4 连接成功后,返回一个PDO类的实例给脚本。可以调用PDO实例的方法实现对数据库的操作 >[info] 此连接在**PDO对象的生存周期中保持活动**。关闭连接,只需要销毁对象并确保所有剩余到它的引用到被删除,可以通过赋值NULL给对象变量。 >[info] 如果没有明确删除,则会在PHP脚本结束时自动关闭连接 ~~~ ;关闭PDO连接 //创建数据库连接 $dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass ); //操作数据库 //操作数据库 //关闭数据库连接 $dbh = null ; ~~~ ### 2-2 PDO预处理语句与存储过程 >[info] 1 PDO可以实现数据库预处理语句。预处理器语句看做待运行的SQL语句的一种模板,可以使用变量参数进行绑定处理。 ~~~ ;使用占位符生成预处理语句准备SQL语句 $stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (:name, :value)" ); ;:name和:value作为命名占位符 $stmt -> bindParam ( ':name' , $name ); $stmt -> bindParam ( ':value' , $value ); // 插入一行 $name = 'one' ; $value = 1 ; $stmt -> execute (); // 用不同的值插入另一行 $name = 'two' ; $value = 2 ; $stmt -> execute (); ~~~ ~~~ ;使用?占位符生成SQL预处理语句 $stmt = $dbh -> prepare ( "INSERT INTO REGISTRY (name, value) VALUES (?, ?)" ); $stmt -> bindParam ( 1 , $name ); $stmt -> bindParam ( 2 , $value ); // 插入一行 $name = 'one' ; $value = 1 ; $stmt -> execute (); // 用不同的值插入另一行 $name = 'two' ; $value = 2 ; $stmt -> execute (); ~~~ >[info] 2 预处理语句可以带来两大好处 >[info] (1) 查询仅仅需要解析或预处理一次,但可以使用相同或不同的参数执行多次。 >[info] 当查询准备后,数据库将分析,编译和优化执行该查询的计划。对于复杂的查询,此过程需要花费较多时间,如果需要以不同参数多次重复相同的查询,该过程将大大降低应用程序的速度 >[info] 通过预处理语句,可以避免重复分析编译优化周期,因此预处理语句占用更少的资源,运行更快 >[info] (2)提供给预处理语句的参数不需要使用引号括起来,驱动程序会自动处理。如果应用程序只需要处理预处理语句,可以确保不会发生SQL注入。(手册照搬) ~~~ ;预处理语句获取数据 $stmt = $dbh -> prepare ( "SELECT * FROM REGISTRY where name = ?" ); if ( $stmt -> execute (array( $_GET [ 'name' ]))) { while ( $row = $stmt -> fetch ()) { print_r ( $row ); } } ~~~ >[info] 3 数据库驱动支持下,应用程序还可以绑定输出和输入参数,输出参数通常用于从存储过程取值。输出参数使用起来比输入参数复杂一些,绑定一个输出参数时,必须知道给的参数的长度。 ~~~ $stmt = $dbh -> prepare ( "CALL sp_returns_string(?)" ); $stmt -> bindParam ( 1 , $return_value , PDO :: PARAM_STR , 4000 ); // 调用存储过程 $stmt -> execute (); print "procedure returned $return_value \n" ; ~~~ >[info] 4 可以指定同时具有输入和输出值的参数,当存储过程返回时,保存输出值 ~~~ $stmt = $dbh -> prepare ( "CALL sp_takes_string_returns_string(?)" ); $value = 'hello' ; $stmt -> bindParam ( 1 , $value , PDO :: PARAM_STR | PDO :: PARAM_INPUT_OUTPUT , 4000 ); // 调用存储过程 $stmt -> execute (); print "procedure returned $value \n" ; ~~~ >[info] 5 注意占位符对于SQL语句完整性的补充 ~~~ $stmt = $dbh -> prepare ( "SELECT * FROM REGISTRY where name LIKE '%?%'" ); $stmt -> execute (array( $_GET [ 'name' ])); // 占位符必须保证SQL语句完整 $stmt = $dbh -> prepare ( "SELECT * FROM REGISTRY where name LIKE ?" ); $stmt -> execute (array( "% $_GET [ name ] %" )); ~~~ ### 2-3 PDO事务和自动提交 >[info] 1 事务可以看做多条SQL语句的顺序组合。事务通常用来实现数据库的ACID特性。事务操作可以根据请求请求整体执行,或者根据请求自动撤销 >[info] 2 事务通常把一些语句准备好同时生效实现的,这样做的好处可以大大提高更改效率。因此脚本更快,更健壮 >[info] 3 事务需要数据库支持,但是并非每种数据库都支持事务,当第一次打开连接时,PDO默认在自动提交模式下运行。自动提交下运行的每个查询都有它自己的事务,如果数据库不支持事务,则没有, >[info] 4 如果需要一个事务,则必须使用PDO::beginTransaction()方法取得,如果底层取得不支持事务,会抛出一个PDOException依次。 >[info] 5 开始事务后,可以使用PDO::commit()或者PDO::rollBack()完成,取决于事务中的代码是否允许成功 >[info] 6 事务查询与复杂查询对比,事务更具有数据库的一致性。 ~~~ ;PDO事务的简单使用 try { $dbh = new PDO ( 'odbc:SAMPLE' , 'db2inst1' , 'ibmdb2' , array( PDO :: ATTR_PERSISTENT => true )); echo "Connected\n" ; } catch ( Exception $e ) { die( "Unable to connect: " . $e -> getMessage ()); } try { $dbh -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION ); $dbh -> beginTransaction (); $dbh -> exec ( "insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')" ); $dbh -> exec ( "insert into salarychange (id, amount, changedate) values (23, 50000, NOW())" ); $dbh -> commit (); } catch ( Exception $e ) { $dbh -> rollBack (); echo "Failed: " . $e -> getMessage (); } ~~~ ### 2-4 PDO大对象 ### 2-5 PDO错误和错误处理 >[info] PDO提供了三种不同的错误处理模式, >[info] (1) PDO::ERRMODE_SILENT 默认模式,可以简单地设置错误码,使用PDO::errorCode()和PDO::errorInfo()方法来检查语句和数据库对象。 >[info] 如果错误是由于对语句对象的调用而产生的,那么可以调用对象的PDOStatement::errorCode()和PDOStatement::errorInfo()方法。如果错误由于调用数据库对象而产生的,可以在数据库对象上调用上述两个方法 >[info] (2) PDO::ERRMODE_WARNING 除了设置错误码后,PDO还将发出一条传统的E_WARNING信息。如果只是想看看发生的问题而且不中断应用程序的流程,此设置经常在调试/测试期间非常有用 >[info] (3) PDO::ERRMODE_EXCEPTION 除了设置错误码后,PDO还将抛出一个PDOException异常类并设置其属性来反射错误码和错误信息,在调试期间非常有用,会有效地放大脚本中产生错误的点,从而可以非常快速地支持代码中问题的潜在区域 >[info] 异常模式可以清晰地构建自己的错误处理,避免传统模式中异常模式的处理组织方式 ~~~ ;创建PDO实例设置错误模式 $dsn = 'mysql:dbname=testdb;host=127.0.0.1' ; $user = 'dbuser' ; $password = 'dbpass' ; try { $dbh = new PDO ( $dsn , $user , $password ); $dbh -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION ); } catch ( PDOException $e ) { echo 'Connection failed: ' . $e -> getMessage (); } ~~~ ~~~ ;在构造函数中设置错误模式 $dsn = 'mysql:dbname=test;host=127.0.0.1' ; $user = 'googleguy' ; $password = 'googleguy' ; try { $dbh = new PDO ( $dsn , $user , $password , array( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_WARNING )); } catch ( PDOException $e ) { echo 'Connection failed: ' . $e -> getMessage (); exit; } $dbh -> query ( "SELECT wrongcolumn FROM wrongtable" ); ~~~ ## 3 PDO类(PHP和数据库服务之间的连接类) ### 1 __construct()构造函数 ~~~ PDO::__construct ( string $dsn [, string $username [, string $password [, array $driver_options ]]] ) ~~~ > $dsn: 数据源名称或叫做DSN,包含了请求连接到数据库的信息,通常一个DSN由PDO驱动名,紧随其后的冒号以及具体的PDO驱动的连接语法组成,支持三种不同方式的DSN >$username: DSN字符串中的用户名 >$password: DSN字符串中的密码 >driver_options: 数据库连接键值对参数 ### 2 setAttribute() PDO属性设置 ~~~ bool PDO::setAttribute ( int $attribute , mixed $value ) ~~~ >常见可设置数据库属性 > $attribute PDO::ATTR_CASE >> 强制列名为指定的大小写。 >> PDO::CASE_LOWER:强制列名小写 >> PDO::CASE_UPPER:强制列名大写。 >> PDO::CASE_NATURAL:保留数据库驱动返回的列名 > $attribute PDO::ATTR_ERRMODE >> 错误报告 >> PDO::ERRMODE_SILENT: 仅仅设置错误代码 >> PDO::ERRMODE_WARNING: 引发警告信息 >> PDO::ERRMODE_EXCEPTION: 抛出异常 > $attribue PDO::ATTR_ORACLE_NULLS >> 空字符串和NULL的转换 >> PDO::NULL_NATURAL: 不转换 >> PDO::NULL_EMPTY_STRING:空字符串转换为NULL >> PDO::NULL_TO_STRING:NULL转换为空字符串 > $attribute PDO::ATTR_STRINGIFY_FETCHES >> 是否将数字值转换为字符串 >> true >> false > $attribute PDO::ATTR_STATEMENT_CLASS >> 设置从PDOStatement派生的用户提供的语句类, >> 使用array(string 类名,array(mixed 构造函数的参数)) > $attribue PDO::ATTR_TIMEOUT >> 设置超时的秒数。 > $attribute PDO::ATTR_AUTOCOMMIT >> 设置是否自动提交每个单独的语句 > $attribue PDO::ATTR_EMULATE_PREPARES >> 开启或关闭预处理语句的模拟 >> true 强制PDO使用模拟预处理语句 >> false 本地预处理语句 > $attribute PDO::MYSQL_ATTR_USE_BUFFERED_QUERY >> 是否使用缓冲查询 >> Mysql中可以使用 > $attribute PDO::ATTR_DEFAULT_FETCH_MODE >> 返回结果的模式 >> 作为PDOStatement::fetch()默认值 > 设置数据库连接属性 ### 3 getAttribute() PDO属性获取 ~~~ mixed PDO::getAttribute ( int $attribute ) ~~~ > $attribute 返回数据库连接属性,下列属性的一个 >> PDO::ATTR_AUTOCOMMIT >> PDO::ATTR_CASE >> PDO::ATTR_CLIENT_VERSION >> PDO::ATTR_CONNECTION_STATUS >> PDO::ATTR_DRIVER_NAME >> PDO::ATTR_ERRMODE >> PDO::ATTR_ORACLE_NULLS >> PDO::ATTR_PERSISTENT >> PDO::ATTR_PREFETCH >> PDO::ATTR_SERVER_INFO >> PDO::ATTR_SERVER_VERSION >> PDO::ATTR_TIMEOUT > 成功调用返回请求的PDO属性值,不成功返回null ~~~ $conn = new PDO ( 'odbc:sample' , 'db2inst1' , 'ibmdb2' ); $attributes = array( "AUTOCOMMIT" , "ERRMODE" , "CASE" , "CLIENT_VERSION" , "CONNECTION_STATUS" , "ORACLE_NULLS" , "PERSISTENT" , "PREFETCH" , "SERVER_INFO" , "SERVER_VERSION" , "TIMEOUT" ); foreach ( $attributes as $val ) { echo "PDO::ATTR_ $val : " ; echo $conn -> getAttribute ( constant ( "PDO::ATTR_ $val " )) . "\n" ; } ~~~ ### 4 getAvailableDrivers() 返回可用驱动的数组 ~~~ static array PDO::getAvailableDrivers ( void ) ~~~ > 返回在PDO::__construct()参数DSN中的PDO可以驱动类型 ~~~ print_r ( PDO :: getAvailableDrivers ()); ~~~ 输出: ~~~ Array ( [0] => mysql [1] => sqlite ) ~~~ ### 5 quote() 语句转义处理 ~~~ public string PDO::quote ( string $string [, int $parameter_type = PDO::PARAM_STR ] ) ~~~ > $string: 待转移语句 > $paratemter_type : 转义风格? ~~~ ;简单语句转义 $conn = new PDO ( 'sqlite:/home/lynn/music.sql3' ); $string = 'Nice' ; print "Unquoted string: $string \n" ; print "Quoted string: " . $conn -> quote ( $string ) . "\n" ; ~~~ 输出 ~~~ Unquoted string: Nice Quoted string: 'Nice' ~~~ ~~~ ;危险语句转义 $conn = new PDO ( 'sqlite:/home/lynn/music.sql3' ); $string = 'Naughty \' string' ; print "Unquoted string: $string \n" ; print "Quoted string:" . $conn -> quote ( $string ) . "\n" ; ~~~ 输出 ~~~ Unquoted string: Naughty ' string Quoted string: 'Naughty '' string' ~~~ ~~~ ;复杂语句转义 $conn = new PDO ( 'sqlite:/home/lynn/music.sql3' ); $string = "Co'mpl''ex \"st'\"ring" ; print "Unquoted string: $string \n" ; print "Quoted string: " . $conn -> quote ( $string ) . "\n" ; ~~~ 输出 ~~~ Unquoted string: Co'mpl''ex "st'"ring Quoted string: 'Co''mpl''''ex "st''"ring' ~~~ ### 6 prepare() 准备待执行SQL语句 ~~~ public PDOStatement PDO::prepare ( string $statement [, array $driver_options = array() ] ) ~~~ > $statement:sql语句 > $driver_options:数据库驱动参数 > 返回待执行的PDOStatement对象 ~~~ ;命名占位符sql语句生成 $sql = 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ; $sth = $dbh -> prepare ( $sql , array( PDO :: ATTR_CURSOR => PDO :: CURSOR_FWDONLY )); $sth -> execute (array( ':calories' => 150 , ':colour' => 'red' )); $red = $sth -> fetchAll (); $sth -> execute (array( ':calories' => 175 , ':colour' => 'yellow' )); $yellow = $sth -> fetchAll (); ~~~ ~~~ ;?占位符sql语句生成 $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?' ); $sth -> execute (array( 150 , 'red' )); $red = $sth -> fetchAll (); $sth -> execute (array( 175 , 'yellow' )); $yellow = $sth -> fetchAll (); ~~~ ### 7 exec() 执行一个SQL语句,返回受此语句影响的行数 ~~~ int PDO::exec ( string $statement ) ~~~ > $statement 被预处理和执行的SQL语句 > 单独函数中执行一条SQL语句,返回受此语句影响的行数 ~~~ $db -> exec () or die( print_r ( $db -> errorInfo (), true )); ~~~ ~~~ $dbh = new PDO ( 'odbc:sample' , 'db2inst1' , 'ibmdb2' ); $count = $dbh -> exec ( "DELETE FROM fruit WHERE colour = 'red'" ); print( "Deleted $count rows.\n" ); ~~~ ### 8 query() 执行SQL语句,返回PDOStatement对象 ~~~ public PDOStatement PDO::query ( string $statement ) public PDOStatement PDO::query ( string $statement , int $PDO::FETCH_COLUMN , int $colno ) public PDOStatement PDO::query ( string $statement , int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) public PDOStatement PDO::query ( string $statement , int $PDO::FETCH_INTO , object $object ) ~~~ > $statement:待执行sql语句 ~~~ function getFruit ( $conn ) { $sql = 'SELECT name, color, calories FROM fruit ORDER BY name' ; foreach ( $conn -> query ( $sql ) as $row ) { print $row [ 'name' ] . "\t" ; print $row [ 'color' ] . "\t" ; print $row [ 'calories' ] . "\n" ; } } ~~~ 输出 ~~~ apple red 150 banana yellow 250 kiwi brown 75 lemon yellow 25 orange orange 300 pear green 150 watermelon pink 90 ~~~ ### 9 beginTransaction 启动事务 ~~~ bool PDO::beginTransaction ( void ) ~~~ > 关闭自动提交,进入事务的手动提交模式 ~~~ /* 开始一个事务,关闭自动提交 */ $dbh -> beginTransaction (); /* 更改数据库架构及数据 */ $sth = $dbh -> exec ( "DROP TABLE fruit" ); $sth = $dbh -> exec ( "UPDATE dessert SET name = 'hamburger'" ); /* 识别出错误并回滚更改 */ $dbh -> rollBack (); /* 数据库连接现在返回到自动提交模式 */ ~~~ ### 10 commint() 手动提交事务 ~~~ bool PDO::commit ( void ) ~~~ > 事务中进行手动提交,返回到自动提交模式 ~~~ /* 开始一个事务,关闭自动提交 */ $dbh -> beginTransaction (); /* 在全有或全无的基础上插入多行记录(要么全部插入,要么全部不插入) */ $sql = 'INSERT INTO fruit (name, colour, calories) VALUES (?, ?, ?)' ; $sth = $dbh -> prepare ( $sql ); foreach ( $fruits as $fruit ) { $sth -> execute (array( $fruit -> name , $fruit -> colour , $fruit -> calories , )); } /* 提交更改 */ $dbh -> commit (); /* 现在数据库连接返回到自动提交模式 */ ~~~ ~~~ /* 开始一个事务,关闭自动提交 */ $dbh -> beginTransaction (); /* Change the database schema */ $sth = $dbh -> exec ( "DROP TABLE fruit" ); /* 更改数据库架构 */ $dbh -> commit (); /* 现在数据库连接返回到自动提交模式 */ ~~~ ### 11 rollBack() 回滚一个事务 ~~~ 回滚由PDO::beginTransaction() 发起的当前事务中的手动提交 设置成自动提交模式,的回滚事务后恢复自动提交模式 包括 MySQL 在内的一些数据库, 当在一个事务内有类似删除或创建数据表等 DLL 语句时,会自动导致一个隐式地提交。隐式地提交将无法回滚此事务范围内的任何更改 ~~~ ~~~ ;在 MySQL 中,DROP TABLE 语句自动提交事务,因此在此事务内的任何更改都不会被回滚。 /* 开始一个事务,关闭自动提交 */ $dbh -> beginTransaction (); /* 更改数据库架构和数据 */ $sth = $dbh -> exec ( "DROP TABLE fruit" ); $sth = $dbh -> exec ( "UPDATE dessert SET name = 'hamburger'" ); /* 识别错误且回滚更改 */ $dbh -> rollBack (); /* 此时数据库连接恢复到自动提交模式 */ ~~~ ### 12 inTransaction() 检查是否在一个事务内 ~~~ bool PDO::inTransaction ( void ) ~~~ > 检查驱动内的一个事务是否处于激活 ### 13 lastInsertId() 返回最后插入行的ID或序列值 ~~~ string PDO::lastInsertId ([ string $name = NULL ] ) ~~~ > 返回ID对应的序列对象的名称 >>如果没有为参数 name 指定序列名称, PDO::lastInsertId() 则返回一个表示最后插入数据库那一行的行ID的字符串。 >>如果为参数 name 指定了序列名称, PDO::lastInsertId() 则返回一个表示从指定序列对象取回最后的值的字符串。 >>如果当前 PDO 驱动不支持此功能,则 PDO::lastInsertId() 触发一个 IM001 SQLSTATE 。 ### 14 errorCode() 获取上次数据库操作错误码 ~~~ mixed PDO::errorCode ( void ) ~~~ > 返回一个SQLSTATE说明码,一个由5个字母或数字组成的SQL标准定义的标识符 ~~~ $dbh -> exec ( "INSERT INTO bones(skull) VALUES ('lucy')" ); echo "\nPDO::errorCode(): " ; print $dbh -> errorCode (); ~~~ 输出 ~~~ PDO::errorCode(): 42S02 ~~~ ### 15 errorInfo() 获取上次数据库操作错误信息 ~~~ public array PDO::errorInfo ( void ) ~~~ > 返回错误信息数组 >> SQLSTATE >> Driver error code >> Driver error message ~~~ $stmt = $dbh -> prepare ( 'bogus sql' ); if (! $stmt ) { echo "\nPDO::errorInfo():\n" ; print_r ( $dbh -> errorInfo ()); } ~~~ 输出 ~~~ PDO::errorInfo(): Array ( [0] => HY000 [1] => 1 [2] => near "bogus": syntax error ) ~~~ ## 4 PDOStatment类(代表预处理语句,执行后保存相关结果集) ### 4-1 $queryString 成员变量 > 代表查询字符串内容 ### 4-2 bindParam() 绑定参数到预处理语句 ~~~ bool PDOStatement::bindParam ( mixed $parameter , mixed &$variable [, int $data_type = PDO::PARAM_STR [, int $length [, mixed $driver_options ]]] ) ~~~ > $paramter 参数标识符 命名占位符:name。问号占位符使用以1为开始索引的参数位置 > $varibale 绑定到参数的变量名 > $data_type 指定参数的类型 > $length 数据类型的长度 > $driver_options 驱动配置参数 > 绑定一个PHP变量到用作预处理的SQL语句中的对应命名占位符或问号占位符。 不同于 PDOStatement::bindValue() ,此变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值。 > 大多数参数是输入参数,即,参数以只读的方式用来建立查询。一些驱动支持调用存储过程并作为输出参数返回数据,一些支持作为输入/输出参数,既发送数据又接收更新后的数据。 ~~~ /* 通过绑定的 PHP 变量执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ); $sth -> bindParam ( ':calories' , $calories , PDO :: PARAM_INT ); $sth -> bindParam ( ':colour' , $colour , PDO :: PARAM_STR , 12 ); $sth -> execute (); ~~~ ~~~ /* 通过绑定的 PHP 变量执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?' ); $sth -> bindParam ( 1 , $calories , PDO :: PARAM_INT ); $sth -> bindParam ( 2 , $colour , PDO :: PARAM_STR , 12 ); $sth -> execute (); ~~~ ~~~ /* 使用 INOUT 参数调用一个存储过程 */ $colour = 'red' ; $sth = $dbh -> prepare ( 'CALL puree_fruit(?)' ); $sth -> bindParam ( 1 , $colour , PDO :: PARAM_STR | PDO :: PARAM_INPUT_OUTPUT , 12 ); $sth -> execute (); print( "After pureeing fruit, the colour is: $colour " ); ~~~ ### 4-3 bindValue() 绑定一个值到一个参数 ~~~ bool PDOStatement::bindValue ( mixed $parameter , mixed $value [, int $data_type = PDO::PARAM_STR ] ) ~~~ > $parameter:参数标识符 命名占位符:name。问号占位符使用以1为开始索引的参数位置 > $value:绑定到参数的值 > $data_type 指定参数的类型 >> PDOStatement::bindValue() ,此变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值 ~~~ /* 通过绑定的 PHP 变量执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ); $sth -> bindValue ( ':calories' , $calories , PDO :: PARAM_INT ); $sth -> bindValue ( ':colour' , $colour , PDO :: PARAM_STR ); $sth -> execute (); ~~~ ~~~ /* 通过绑定的 PHP 变量执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?' ); $sth -> bindValue ( 1 , $calories , PDO :: PARAM_INT ); $sth -> bindValue ( 2 , $colour , PDO :: PARAM_STR ); $sth -> execute (); ~~~ ### 4-4 bindColumn() 绑定一列到一个PHP变量 ~~~ bool PDOStatement::bindColumn ( mixed $column , mixed &$param [, int $type [, int $maxlen [, mixed $driverdata ]]] ) ~~~ > $column 结果集中的列号(从1开始索引)或列名。如果使用列名,注意名称应该与由驱动返回的列名大小写保持一致。 > $param 将绑定到列的 PHP 变量名称 > $type 通过 PDO::PARAM_* 常量指定的参数的数据类型。 > $maxlen 预分配提示。 > $driverdata 驱动的可选参数。 ~~~ ;结果集输出绑定到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 ); ~~~ 输出 ~~~ apple red 150 banana yellow 175 kiwi green 75 orange orange 150 mango red 200 strawberry red 25 ~~~ ### 4-5 execute() 执行PDO::prepare()生成的预处理语句 ~~~ bool PDOStatement::execute ([ array $input_parameters ] ) ~~~ > $input_parameters:绑定参数列表 >> 1.调用 PDOStatement::bindParam() 绑定 PHP 变量到参数标记:如果有的话,通过关联参数标记绑定的变量来传递输入值和取得输出值 >> 2.或传递一个只作为输入参数值的数组 ~~~ ;绑定变量到预处理语句并执行 $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ); $sth -> bindParam ( ':calories' , $calories , PDO :: PARAM_INT ); $sth -> bindParam ( ':colour' , $colour , PDO :: PARAM_STR , 12 ); $sth -> execute (); ~~~ ~~~ /* 通过传递一个含有插入值的数组执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ); $sth -> execute (array( ':calories' => $calories , ':colour' => $colour /* ~~~ ~~~ ;通过传递一个含有插入值的数组执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ); $sth -> execute (array( ':calories' => $calories , ':colour' => $colour ));)); ~~~ ### 4-3 fetch() 从结果集中获取下一行 ~~~ mixed PDOStatement::fetch ([ int $fetch_style [, int $cursor_orientation = PDO::FETCH_ORI_NEXT [, int $cursor_offset = 0 ]]] ) ~~~ > $fetch_style >> 控制下一行如何返回给调用者。此值必须是 PDO::FETCH_* 系列常量中的一个,缺省为 PDO::ATTR_DEFAULT_FETCH_MODE 的值 (默认为 PDO::FETCH_BOTH )。 >> 1. PDO::FETCH_ASSOC:返回一个索引为结果集列名的数组 >> 2. PDO::FETCH_BOTH(默认):返回一个索引为结果集列名和以0开始的列号的数组 >> 3. PDO::FETCH_BOUND:返回 TRUE ,并分配结果集中的列值给 PDOStatement::bindColumn() 方法绑定的 PHP 变量。 >> 4. PDO::FETCH_CLASS:返回一个请求类的新实例,映射结果集中的列名到类中对应的属性名。如果 fetch_style 包含 PDO::FETCH_CLASSTYPE(例如:PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE),则类名由第一列的值决定 >> 5. PDO::FETCH_INTO:更新一个被请求类已存在的实例,映射结果集中的列到类中命名的属性 >> 6. PDO::FETCH_LAZY:结合使用 PDO::FETCH_BOTH 和 PDO::FETCH_OBJ,创建供用来访问的对象变量名 >> 7. PDO::FETCH_NUM:返回一个索引为以0开始的结果集列号的数组 >> 8. PDO::FETCH_OBJ:返回一个属性名对应结果集列名的匿名对象 > $cursor_orientation >>对于 一个 PDOStatement 对象表示的可滚动游标,该值决定了哪一行将被返回给调用者。此值必须是 PDO::FETCH_ORI_* 系列常量中的一个,默认为 PDO::FETCH_ORI_NEXT。要想让 PDOStatement 对象使用可滚动游标,必须在用 PDO::prepare() 预处理SQL语句时,设置 PDO::ATTR_CURSOR 属性为 PDO::CURSOR_SCROLL。 > $offset >> 对于一个 cursor_orientation 参数设置为 PDO::FETCH_ORI_ABS 的PDOStatement 对象代表的可滚动游标,此值指定结果集中想要获取行的绝对行号。 >> 对于一个 cursor_orientation 参数设置为 PDO::FETCH_ORI_REL 的PDOStatement 对象代表的可滚动游标,此值指定想要获取行相对于调用 PDOStatement::fetch() 前游标的位置 > 从PDOStatement::execute()执行预处理语句的结果集中获取下一行。返回值依赖于PDO中PDO::FETCH_* 的配置 >Eg1: 使用不同的提取方式获取行 ~~~ $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); /* 运用 PDOStatement::fetch 风格 */ print( "PDO::FETCH_ASSOC: " ); print( "Return next row as an array indexed by column name\n" ); $result = $sth -> fetch ( PDO :: FETCH_ASSOC ); print_r ( $result ); print( "\n" ); print( "PDO::FETCH_BOTH: " ); print( "Return next row as an array indexed by both column name and number\n" ); $result = $sth -> fetch ( PDO :: FETCH_BOTH ); print_r ( $result ); print( "\n" ); print( "PDO::FETCH_LAZY: " ); print( "Return next row as an anonymous object with column names as properties\n" ); $result = $sth -> fetch ( PDO :: FETCH_LAZY ); print_r ( $result ); print( "\n" ); print( "PDO::FETCH_OBJ: " ); print( "Return next row as an anonymous object with column names as properties\n" ); $result = $sth -> fetch ( PDO :: FETCH_OBJ ); print $result -> NAME ; print( "\n" ); ~~~ 输出 ~~~ PDO::FETCH_ASSOC: Return next row as an array indexed by column name Array ( [NAME] => apple [COLOUR] => red )PDO::FETCH_BOTH: Return next row as an array indexed by both column name and number Array ( [NAME] => banana [0] => banana [COLOUR] => yellow [1] => yellow )PDO::FETCH_LAZY: Return next row as an anonymous object with column names as properties PDORow Object ( [NAME] => orange [COLOUR] => orange )PDO::FETCH_OBJ: Return next row as an anonymous object with column names as properties kiwi ~~~ > Eg2:使用可滚动游标获取行 ~~~ function readDataForwards ( $dbh ) { $sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY BET' ; try { $stmt = $dbh -> prepare ( $sql , array( PDO :: ATTR_CURSOR => PDO :: CURSOR_SCROLL )); $stmt -> execute (); while ( $row = $stmt -> fetch ( PDO :: FETCH_NUM , PDO :: FETCH_ORI_NEXT )) { $data = $row [ 0 ] . "\t" . $row [ 1 ] . "\t" . $row [ 2 ] . "\n" ; print $data ; } $stmt = null ; } catch ( PDOException $e ) { print $e -> getMessage (); } } function readDataBackwards ( $dbh ) { $sql = 'SELECT hand, won, bet FROM mynumbers ORDER BY bet' ; try { $stmt = $dbh -> prepare ( $sql , array( PDO :: ATTR_CURSOR => PDO :: CURSOR_SCROLL )); $stmt -> execute (); $row = $stmt -> fetch ( PDO :: FETCH_NUM , PDO :: FETCH_ORI_LAST ); do { $data = $row [ 0 ] . "\t" . $row [ 1 ] . "\t" . $row [ 2 ] . "\n" ; print $data ; } while ( $row = $stmt -> fetch ( PDO :: FETCH_NUM , PDO :: FETCH_ORI_PRIOR )); $stmt = null ; } catch ( PDOException $e ) { print $e -> getMessage (); } } print "Reading forwards:\n" ; readDataForwards ( $conn ); print "Reading backwards:\n" ; readDataBackwards ( $conn ); ~~~ 输出 ~~~ Reading forwards: 21 10 5 16 0 5 19 20 10Reading backwards: 19 20 10 16 0 5 21 10 5 ~~~ ### 4-5 fetchAll() 返回结果集中所有行的数组 ~~~ array PDOStatement::fetchAll ([ int $fetch_style [, mixed $fetch_argument [, array $ctor_args = array() ]]] ) ~~~ > $fetch_style 结果集类型 > $fetch_argument 结果列参数 >> PDO::FETCH_COLUMN :返回指定以0开始索引的列。 >> PDO::FETCH_CLASS :返回指定类的实例,映射每行的列到类中对应的属性名。 >> PDO::FETCH_FUNC :将每行的列作为参数传递给指定的函数,并返回调用函数后的结果。 > $ctor_args 自定义类的构造函数的参数。 >> 当 fetch_style 参数为 PDO::FETCH_CLASS 时,自定义类的构造函数的参数。 > 返回包含结果集中所有剩余行的数组。此数组的每一行要么是一个列值的数组,要么是属性对应每个列名的一个对象。 > 使用此方法获取大结果集将导致系统负担加重且可能占用大量网络资源。与其取回所有数据后用PHP来操作,倒不如考虑使用数据库服务来处理结果集。例如,在取回数据并通过PHP处理前,在 SQL 中使用 WHERE 和 ORDER BY 子句来限定结果。 ~~~ ;获取结果集中所有剩余的行 $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); /* 获取结果集中所有剩余的行 */ print( "Fetch all of the remaining rows in the result set:\n" ); $result = $sth -> fetchAll (); print_r ( $result ); ~~~ 输出 ~~~ Fetch all of the remaining rows in the result set: Array ( [0] => Array ( [NAME] => pear [0] => pear [COLOUR] => green [1] => green ) [1] => Array ( [NAME] => watermelon [0] => watermelon [COLOUR] => pink [1] => pink )) ~~~ ~~~ ;获取结果集中单独一列的所有值 $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); /* 获取第一列所有值 */ $result = $sth -> fetchAll ( PDO :: FETCH_COLUMN , 0 ); var_dump ( $result ); ~~~ ~~~ Array(3) ( [0] => string(5) => apple [1] => string(4) => pear [2] => string(10) => watermelon ) ~~~ ~~~ ;根据单独的一列把所有值分组 $insert = $dbh -> prepare ( "INSERT INTO fruit(name, colour) VALUES (?, ?)" ); $insert -> execute (array( 'apple' , 'green' )); $insert -> execute (array( 'pear' , 'yellow' )); $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); /* 根据第一列分组 */ var_dump ( $sth -> fetchAll ( PDO :: FETCH_COLUMN | PDO :: FETCH_GROUP )); ~~~ 输出 ~~~ array(3) { ["apple"]=> array(2) { [0]=> string(5) "green" [1]=> string(3) "red" } ["pear"]=> array(2) { [0]=> string(5) "green" [1]=> string(6) "yellow" } ["watermelon"]=> array(1) { [0]=> string(5) "green" } } ~~~ ~~~ ;返回每行结果实例化为一个类 class fruit { public $name ; public $colour ; } $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); $result = $sth -> fetchAll ( PDO :: FETCH_CLASS , "fruit" ); var_dump ( $result ); ~~~ 输出 ~~~ array(3) { [0]=> object(fruit)#1 (2) { ["name"]=> string(5) "apple" ["colour"]=> string(5) "green" } [1]=> object(fruit)#2 (2) { ["name"]=> string(4) "pear" ["colour"]=> string(6) "yellow" } [2]=> object(fruit)#3 (2) { ["name"]=> string(10) "watermelon" ["colour"]=> string(4) "pink" } } ~~~ ~~~ ;每行调用一次函数 function fruit ( $name , $colour ) { return " { $name } : { $colour } " ; } $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); $result = $sth -> fetchAll ( PDO :: FETCH_FUNC , "fruit" ); var_dump ( $result ); ~~~ 输出 ~~~ array(3) { [0]=> string(12) "apple: green" [1]=> string(12) "pear: yellow" [2]=> string(16) "watermelon: pink" } ~~~ ### 4-6 fetchColumn() 返回结果集中的下一行单独的一列 ~~~ string PDOStatement::fetchColumn ([ int $column_number = 0 ] ) ~~~ > $column_number 从行里取回的列的索引数字。)。如果没有提供值,则 PDOStatement::fetchColumn() 获取第一列 > 从结果集中的下一行返回单独的一列,如果没有了,则返回 FALSE 。 ~~~ ;返回下一行的第一列 $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); $sth -> execute (); /* 从结果集中的下一行获取第一列 */ print( "从结果集中的下一行获取第一列:\n" ); $result = $sth -> fetchColumn (); print( "name = $result \n" ); print( "从结果集中的下一行获取第二列:\n" ); $result = $sth -> fetchColumn ( 1 ); print( "colour = $result \n" ); ~~~ 输出 ~~~ 从结果集中的下一行获取第一列: name = lemon 从结果集中的下一行获取第二列: colour = red ~~~ ### 4-7 fetchObject() 将下一行作为一个对象返回 ~~~ mixed PDOStatement::fetchObject ([ string $class_name = "stdClass" [, array $ctor_args ]] ) ~~~ > $class_name 结果类的名称 > $ctor_args 构造函数的参数 > 返回一个属性名对应列表的类的实例 ### 4-8 columnCount() 返回结果集的列数 ~~~ int PDOStatement::columnCount ( void ) ~~~ > 使用 PDOStatement::columnCount() 返回由 PDOStatement 对象代表的结果集中的列数。 > 如果是由 PDO::query() 返回的 PDOStatement 对象,则列数计算立即可用。 > 如果是由 PDO::prepare() 返回的 PDOStatement 对象,则在调用 PDOStatement::execute() 之前都不能准确地计算出列数。 ~~~ ;计算列数 $dbh = new PDO ( 'odbc:sample' , 'db2inst1' , 'ibmdb2' ); $sth = $dbh -> prepare ( "SELECT name, colour FROM fruit" ); /* 计算一个(不存在)的结果集中的列数 */ $colcount = $sth -> columnCount (); print( "Before execute(), result set has $colcount columns (should be 0)\n" ); $sth -> execute (); /* 计算结果集中的列数 */ $colcount = $sth -> columnCount (); print( "After execute(), result set has $colcount columns (should be 2)\n" ); ~~~ ### 4-9 rowCount() 返回受SQL语句影响的行数 ~~~ int PDOStatement::rowCount ( void ) ~~~ > PDOStatement::rowCount() 返回上一个由对应的 PDOStatement 对象执行DELETE、 INSERT、或 UPDATE 语句受影响的行数。 > 如果上一条由相关 PDOStatement 执行的 SQL 语句是一条 SELECT 语句,有些数据可能返回由此语句返回的行数。但这种方式不能保证对所有数据有效,且对于可移植的应用不应依赖于此方式。 ~~~ ;返回删除的行数 /* 从 FRUIT 数据表中删除所有行 */ $del = $dbh -> prepare ( 'DELETE FROM fruit' ); $del -> execute (); /* 返回被删除的行数 */ print( "Return number of rows that were deleted:\n" ); $count = $del -> rowCount (); ~~~ 输出 ~~~ Return number of rows that were deleted: Deleted 9 rows. ~~~ ~~~ ;返回select语句返回的行数 $sql = "SELECT COUNT(*) FROM fruit WHERE calories > 100" ; if ( $res = $conn -> query ( $sql )) { /* 检查符合 SELECT 语句的行数 */ if ( $res -> fetchColumn () > 0 ) { /* 发出一条真正的 SELECT 语句并操作返回的结果 */ $sql = "SELECT name FROM fruit WHERE calories > 100" ; foreach ( $conn -> query ( $sql ) as $row ) { print "Name: " . $row [ 'NAME' ] . "\n" ; } } /* 没有匹配的行 -- 执行其他 */ else { print "No rows matched the query." ; } } $res = null ; $conn = null ; ~~~ 输出 ~~~ apple banana orange pear ~~~ ### 4-10 nextRowset() 在一个多行集语句句柄中推进到下一个行集 ~~~ bool PDOStatement::nextRowset ( void ) ~~~ > 一些数据库服务支持返回一个以上行集(也被称为结果集)的存储过程。 PDOStatement::nextRowset() 使你能够结合一个 PDOStatement 对象访问第二个以及后续的行集。上述的每个行集可以有不同的列集合。 ~~~ ;获取一个存储过程返回的多个行集 $sql = 'CALL multiple_rowsets()' ; $stmt = $conn -> query ( $sql ); $i = 1 ; do { $rowset = $stmt -> fetchAll ( PDO :: FETCH_NUM ); if ( $rowset ) { printResultSet ( $rowset , $i ); } $i ++; } while ( $stmt -> nextRowset ()); function printResultSet (& $rowset , $i ) { print "Result set $i :\n" ; foreach ( $rowset as $row ) { foreach ( $row as $col ) { print $col . "\t" ; } print "\n" ; } print "\n" ; } ~~~ 输出 ~~~ Result set 1: apple red banana yellowResult set 2: orange orange 150 banana yellow 175Result set 3: lime green apple red banana yellow ~~~ ### 4-11 getColumnMeta() 返回结果集中一列的元数据 ~~~ array PDOStatement::getColumnMeta ( int $column ) ~~~ ### 4-12 关闭游标,语句可以再次被执行 ~~~ bool PDOStatement::closeCursor ( void ) ~~~ > PDOStatement::closeCursor() 释放到数据库服务的连接,以便发出其他 SQL 语句,但使语句处于一个可以被再次执行的状态。 > PDOStatement::closeCursor() 要么是一个可选驱动的特有方法(效率最高)来实现,要么是在没有驱动特定的功能时作为一般的PDO 备用来实现。一般的备用语义上与下面的 PHP 代码相同: ~~~ do { while ( $stmt -> fetch ()) ; if (! $stmt -> nextRowset ()) break; } while ( true ); ~~~ ~~~ /* 创建一个 PDOStatement 对象 */ $stmt = $dbh -> prepare ( 'SELECT foo FROM bar' ); /* 创建第二个 PDOStatement 对象 */ $otherStmt = $dbh -> prepare ( 'SELECT foobaz FROM foobar' ); /* 执行第一条语句 */ $stmt -> execute (); /* 从结果集中只取出第一行 */ $stmt -> fetch (); /* The following call to closeCursor() may be required by some drivers */ $stmt -> closeCursor (); /* 现在可以执行第二条语句了 */ $otherStmt -> execute (); ~~~ ### 4-13 errorCode() 返回错误码 ~~~ string PDOStatement::errorCode ( void ) ~~~ > 与 PDO::errorCode() 相同,只是 PDOStatement::errorCode() 只取回 PDOStatement 对象执行操作中的错误码。 ~~~ ;获取SQLSTATE错误码 /* 引发一个错误 -- BONES 数据表不存在 */ $err = $dbh -> prepare ( 'SELECT skull FROM bones' ); $err -> execute (); echo "\nPDOStatement::errorCode(): " ; print $err -> errorCode (); ~~~ 输出 ~~~ PDOStatement::errorCode(): 42S02 ~~~ ### 4-14 errorInfo() 返回错误信息 ~~~ array PDOStatement::errorInfo ( void ) ~~~ > PDOStatement::errorInfo() 返回一个关于上一次语句句柄执行操作的错误信息的数组 。该数组包含下列字段: > 0 SQLSTATE 错误码 1 具体驱动错误码。 2 具体驱动错误信息。 ~~~ /* 激发一个错误 -- BONES 数据表不存在 */ $sth = $dbh -> prepare ( 'SELECT skull FROM bones' ); $sth -> execute (); echo "\nPDOStatement::errorInfo():\n" ; $arr = $sth -> errorInfo (); print_r ( $arr ); ~~~ 输出 ~~~ PDOStatement::errorInfo(): Array ( [0] => 42S02 [1] => -204 [2] => [IBM][CLI Driver][DB2/LINUX] SQL0204N "DANIELS.BONES" is an undefined name. SQLSTATE=42704 ) ~~~ ### 4-15 setAttribute() 设置语句的属性 ~~~ bool PDOStatement::setAttribute ( int $attribute , mixed $value ) ~~~ > 设置特定数据库驱动语句的属性 >> PDO::ATTR_CURSOR_NAME (Firebird 和 ODBC 特性): 为 UPDATE ... WHERE CURRENT OF 设置游标名称。 ### 4-16 getAttribute() 获取语句的属性 ~~~ mixed PDOStatement::getAttribute ( int $attribute ) ~~~ > 获取特定数据库驱动语句的属性 >> PDO::ATTR_CURSOR_NAME (Firebird 和 ODBC 特性): 为 UPDATE ... WHERE CURRENT OF 设置游标名称。 ### 4-17 setFetchMode() 设置语句的获取模式 ~~~ bool PDOStatement::setFetchMode ( int $mode ) bool PDOStatement::setFetchMode ( int $PDO::FETCH_COLUMN , int $colno ) bool PDOStatement::setFetchMode ( int $PDO::FETCH_CLASS , string $classname , array $ctorargs ) bool PDOStatement::setFetchMode ( int $PDO::FETCH_INTO , object $object ) ~~~ > $mode PDO::FETCH_*系列常量的一个 >> 1 PDO::FETCH_ASSOC:返回一个索引为结果集列名的数组 >> 2 PDO::FETCH_BOTH(默认):返回一个索引为结果集列名和以0开始的列号的数组 >> 3 PDO::FETCH_BOUND:返回 TRUE ,并分配结果集中的列值给 PDOStatement::bindColumn() 方法绑定的 PHP 变量。 >> 4 PDO::FETCH_CLASS:返回一个请求类的新实例,映射结果集中的列名到类中对应的属性名。如果 fetch_style 包含 PDO::FETCH_CLASSTYPE(例如:PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE),则类名由第一列的值决定 >> 5 PDO::FETCH_INTO:更新一个被请求类已存在的实例,映射结果集中的列到类中命名的属性 >> 6 PDO::FETCH_LAZY:结合使用 PDO::FETCH_BOTH 和 PDO::FETCH_OBJ,创建供用来访问的对象变量名 >> 7 PDO::FETCH_NUM:返回一个索引为以0开始的结果集列号的数组 >> 8 PDO::FETCH_OBJ:返回一个属性名对应结果集列名的匿名对象 > $colno 列号 > $classname 类名 > $ctorargs 构造函数参数 > $object 对象 ~~~ ;设置获取模式 $sql = 'SELECT name, colour, calories FROM fruit' ; try { $stmt = $dbh -> query ( $sql ); $result = $stmt -> setFetchMode ( PDO :: FETCH_NUM ); while ( $row = $stmt -> fetch ()) { print $row [ 0 ] . "\t" . $row [ 1 ] . "\t" . $row [ 2 ] . "\n" ; } } catch ( PDOException $e ) { print $e -> getMessage (); } ~~~ 输出 ~~~ apple red 150 banana yellow 250 orange orange 300 kiwi brown 75 lemon yellow 25 pear green 150 watermelon pink 90 ~~~ ###4-18 debugDumpParams() 打印SQL预处理命令 ~~~ bool PDOStatement::debugDumpParams ( void ) ~~~ > 直接打印出一条预处理语句包含的信息。提供正在使用的 SQL 查询、所用参数(Params)的数目、参数的清单、参数名、用一个整数表示的参数类型(paramtype)、键名或位置、值、以及在查询中的位置(如果当前 POD 驱动不支持,则为-1)。 > 此为一个用于调试的功能,在正常输出的情况下直接输出数据。 > 和直接将结果输出到浏览器一样,可使用输出控制函数来捕获当前函数的输出,然后(例如)保存到一个 string 中。只打印此时此刻语句中的参数。额外的参数不存储在语句中,也就不会被输出。 ~~~ /* 通过绑定 PHP 变量执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour' ); $sth -> bindParam ( ':calories' , $calories , PDO :: PARAM_INT ); $sth -> bindValue ( ':colour' , $colour , PDO :: PARAM_STR , 12 ); $sth -> execute (); $sth -> debugDumpParams (); ~~~ 输出 ~~~ SQL: [96] SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour Params: 2 Key: Name: [9] :calories paramno=-1 name=[9] ":calories" is_param=1 param_type=1 Key: Name: [7] :colour paramno=-1 name=[7] ":colour" is_param=1 param_type=2 ~~~ ~~~ ;使用未命名参数的例子 /* 通过绑定 PHP 变量执行一条预处理语句 */ $calories = 150 ; $colour = 'red' ; $name = 'apple' ; $sth = $dbh -> prepare ( 'SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ?' ); $sth -> bindParam ( 1 , $calories , PDO :: PARAM_INT ); $sth -> bindValue ( 2 , $colour , PDO :: PARAM_STR ); $sth -> execute (); $sth -> debugDumpParams (); ~~~ 输出 ~~~ SQL: [82] SELECT name, colour, calories FROM fruit WHERE calories < ? AND colour = ? Params: 2 Key: Position #0: paramno=0 name=[0] "" is_param=1 param_type=1 Key: Position #1: paramno=1 name=[0] "" is_param=1 param_type=2 ~~~ ## 5 PDOException异常类 ## 6 PDO常见驱动