mysql pdo 预处理_PHP PDO预处理语句详解

在生成网页时,许多 PHP 脚本通常都会执行除参数以外,其他部分完全相同的查询语句,针对这种重复执行一个查询,每次迭代使用不同的参数情况,PDO 提供了一种名为预处理语句(prepared statement)的机制,如下图所示。

8ab8df4f8257d411ee7772ad7f449f5a.gif

图:预处理语句的机制

使用预处理机制可以将整个 SQL 命令向数据库服务器发送一次,以后当参数发生变化时,数据库服务器只需对命令的结构做一次分析就够了,即编译一次,可以多次执行。预处理机制会在服务器上缓存查询的语句和执行过程,同时只在服务器和客户端之间传输有变化的值,以此来消除一些额外的开销。这不仅大大减少了需要传输的数据量,还提高了命令的处理效率。可以有效防止 SQL 注入,在执行单个查询时快于直接使用 query()、exec() 的方法,速度快而且安全,非常推荐使用。

了解 PDOStatement 对象

PDO 对预处理语句的支持需要使用 PDOStatement 类对象,但该类的对象并不是通过 new 关键字实例化出来的,而是通过执行 PDO 对象中的 prepare() 方法,在数据库服务器中准备好一个预处理的 SQL 语句后直接返回的。

与使用 query() 方法返回的 PDOStatement 类对象不同,query() 返回的是一个结果集对象,而使用 prepare() 方法返回的则是一个查询对象,能够通过这个对象定义和执行 SQL 命令。

PDOStatement 类中的全部成员方法如下表所示。

方法名

描述

bindColumn()

用来匹配列名和一个指定的变量名,这样每次获取各行记录时,会自动将相应的列值赋给该变量

bindParam()

将参数绑定到相应的查询占位符上

bindValue()

将值绑定到一个对应的参数中

closeCursor()

关闭游标,使该声明再次被执行

columnCount()

在结果集中返回列的数目

errorCode()

获取错误码

errorInfo()

获取错误的信息

execute()

负责执行一个准备好的预处理查询

fetch()

返回结果集的下一行,当到达结果集末尾时返回 false

fetchAll()

获取结果集中的所有行,并赋给返回的数组

fetchColumn()

返回结果集中下一行某个列的值

fetchObject()

获取下一行记录并将其作为一个对象返回

getAttribute()

获取一个声明属性

getColumnMeta()

在结果集中返回某一列的属性信息

nextRowset()

检索下一行集(结果集)

rowCount()

返回执行 DQL 语句后查询结果的记录行数,或返回执行 DML 语句后受影响的记录行总数

setAttribute()

为一个预处理语句设置属性

setFetchMode()

设置获取结果集合的类型

准备语句

当某个 SQL 语句需要重复执行,且每次执行仅仅是使用的参数不同时,使用预处理语句的运行效率最高。使用预处理语句,首先需要在数据库服务器中先准备好一个 SQL 语句,但并不需要马上执行它。

SQL 语句中,对于在执行时需要变化的一些值,可以使用占位符号来取代,然后将这个编辑好的 SQL 语句放到数据库服务器的缓存区等待处理,然后再去单独赋予占位符号具体的值,再通知这个准备好的预处理语句执行即可。

在 PDO 中有两种使用占位符的语法,分别是“命名参数”和“问号参数”,具体使用哪一种语法根据看个人的喜好随意选择即可。

1) 命名参数

命名参数法就是自定义一个字符串作为参数的名称,这个名称需要使用冒号(:)开始,参数的命名要有一定意义,最好和对应的字段名称相同。使用命名参数作为占位符的 INSERT 查询语句如下所示:

$dbh->prepare("INSERT INTO user(name, address, phone) VALUES(:name, :address, :phone)");

2) 问号参数

顾名思义就是使用问号(?)作为占位符,另外问号出现的位置一定要和字段的位置顺序对应。使用问号参数作为占位符的 INSERT 查询语句如下所示:

$dbh->prepare("INSERT INTO user(name, address, phone) VALUES(?, ?, ?)");

注意:不管是使用哪一种参数作为占位符构成的 SQL 语句,哪怕是语句中没有用到占位符,都需要使用 PDO 对象中的 prepare() 方法去准备这个将要用于迭代执行的语句,并返回 PDOStatement 类对象。

绑定参数

当 SQL 语句通过 PDO 对象中的 prepare() 方法,在数据库服务器端准备好之后,如果 SQL 语句使用了占位符,就需要在每次执行时绑定具体的参数。可以通过 PDOStatement 对象中的 bindParam() 方法,把参数变量绑定到准备好的占位符上。bindParam() 方法的语法格式如下所示:

PDOStatement::bindParam(mixed $parameter, mixed &$variable[, int $data_type = PDO::PARAM_STR[, int $length[, mixed $driver_options]]])

参数说明如下:

$parameter:参数标识符。对于使用命名占位符的预处理语句,是类似 :name 形式的参数名。对于使用问号占位符的预处理语句,应是以 1 开始索引的参数位置;

$variable:绑定到 SQL 语句参数的 PHP 变量名,因为该参数是按引用传递的,所以只能提供变量作为参数,不能直接提供数值;

$data_type:可选参数,表示使用 PDO::PARAM_* 常量明确地指定参数的类型。可以为以下值:

PDO:PARAM_BOOL:代表 boolean 数据类型;

PDO:PARAM_NULL:代表 SQL 中 NULL 类型;

PDO:PARAM_INT:代表 SQL 中 INTEGER 数据类型;

PDO:PARAM_STR:代表 SQL 中 CHAR、VARCHAR 和其他字符串数据类型;

PDO:PARAM_LOB:代表 SQL 中大对象数据类型。

$length:可选参数,用来指定数据类型的长度;

$driver_options:可选参数,通过该参数提供任何数据库驱动程序特定的选项。

【示例】将前面使用两种占位符语法准备的 SQL 查询,使用 bindParam() 方法分别绑定上对应的参数。

// 省略部分代码

// 命名参数

$query = "INSERT INTO user (name, address, phone) VALUES (:name, :address, :phone)";

$stmt = $dbh -> prepare($query);

$name = 'C语言中文网';

$address = 'http://c.biancheng.net/php/';

$phone = '15012345678';

$stmt -> bindParam(':name', $name);

$stmt -> bindParam(':address', $address);

$stmt -> bindParam(':phone', $phone);

?>

// 省略部分代码

// 问号参数

$query = "INSERT INTO user (name, address, phone) VALUES (?, ?, ?)";

$stmt = $dbh -> prepare($query);

$name = 'C语言中文网';

$address = 'http://c.biancheng.net/php/';

$phone = '15012345678';

$stmt -> bindParam('1', $name, PDO::PARAM_STR);

$stmt -> bindParam('2', $address, PDO::PARAM_STR);

$stmt -> bindParam('3', $phone, PDO::PARAM_STR, 11);

?>

执行准备好的查询

当准备好查询并绑定了相应的参数后,就可以通过调用 PDOStatement 类对象中的 execute() 方法,反复执行在数据库缓存区准备好的语句了。

【示例】向 user 表中,使用预处理方式连续执行同一个 INSERT 语句,通过改变不同的参数添加两条记录。如下所示:

try{

$dbh = new PDO('mysql:dbname=testdb;host=localhost', 'root', 'root');

}catch(PDOException $e){

echo '数据库连接失败:'.$e->getMessage();

exit();

}

$query = "INSERT INTO user (name, address, phone) VALUES (:name, :address, :phone)";

$stmt = $dbh -> prepare($query);

$name = '张三';

$address = '中国';

$phone = '15012345678';

$stmt -> bindParam(':name', $name);

$stmt -> bindParam(':address', $address);

$stmt -> bindParam(':phone', $phone);

$stmt -> execute();

$name = '李四';

$address = '中国';

$phone = '15087654321';

$stmt -> bindParam(':name', $name);

$stmt -> bindParam(':address', $address);

$stmt -> bindParam(':phone', $phone);

$stmt -> execute();

?>

另外,execute() 方法还可以接收一个数组作为参数,该参数是由 SQL 语句中的命名参数占位符组成的数组,这是第二种为预处理语句中参数赋值的方式。使用这种方式可以省去对 $stmt->bindParam() 的调用。示例代码如下所示:

try{

$dbh = new PDO('mysql:dbname=testdb;host=localhost', 'root', 'root');

}catch(PDOException $e){

echo '数据库连接失败:'.$e->getMessage();

exit();

}

$query = "INSERT INTO user (name, address, phone) VALUES (:name, :address, :phone)";

$stmt = $dbh -> prepare($query);

$stmt -> execute(array(':name'=>'张三', ':address'=>'中国', ':phone'=>'15012345678'));

$arr = [

':name'=>'李四',

':address'=>'中国',

':phone'=>'15087654321'

];

$stmt -> execute($arr);

?>

获取数据

PDO 的获取查询结果的方法我们前面已经详细的介绍过了,这里就不再重复介绍了。详细信息大家可以翻阅《使用PDO获取查询结果》一节。

不管是使用 PDO 对象中的 query() 方法,还是使用 prepare() 和 execute() 等方法结合的预处理语句,执行 SELECT 查询语句都会得到相同的结果集对象 PDOStatement。都需要通过 PDOStatement 类对象中的方法将数据遍历出来。

【示例】下面就分别使用 fetch() 和 fetchAll() 两种方式来获取结果集中的数据

try{

$dbh = new PDO('mysql:dbname=testdb;host=localhost', 'root', 'root');

}catch(PDOException $e){

echo '数据库连接失败:'.$e->getMessage();

exit();

}

$query = "SELECT name,address,phone FROM user";

$stmt = $dbh -> prepare($query);

$stmt -> execute();

while(list($name, $address, $phone) = $stmt -> fetch(PDO::FETCH_NUM)){

echo $name.$address.$phone.'
';

}

?>

try{

$dbh = new PDO('mysql:dbname=testdb;host=localhost', 'root', 'root');

}catch(PDOException $e){

echo '数据库连接失败:'.$e->getMessage();

exit();

}

$query = "SELECT name,address,phone FROM user";

$stmt = $dbh -> prepare($query);

$stmt -> execute();

$data = $stmt -> fetchAll(PDO::FETCH_ASSOC);

echo '

';

foreach ($data as $key => $value) {

var_dump($value);

}

?>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: `pdo_mysql.default_socket` 是 PHP 的配置选项之一,它用于指定 MySQL 数据库服务器的 Unix 套接字文件路径。当使用 PDO 连接 MySQL 数据库时,如果没有手动指定连接参数的 Unix 套接字路径,那么 PDO 将会使用 `pdo_mysql.default_socket` 指定的路径作为默认值。 如果你的 MySQL 数据库服务器安装在默认的位置,并且 PHPMySQL 安装在同一台服务器上,你可以将 `pdo_mysql.default_socket` 设置为 `/var/run/mysqld/mysqld.sock`,这是许多 Linux 系统上 MySQL 默认的 Unix 套接字路径。如果你的 MySQL 数据库服务器安装在不同的位置,你需要根据实际情况修改 `pdo_mysql.default_socket` 的值。 你可以通过修改 `php.ini` 文件来设置 `pdo_mysql.default_socket`。在 `php.ini` 文件中搜索 `pdo_mysql.default_socket`,并将其设置为你需要的 Unix 套接字路径。如果你不知道 Unix 套接字文件的路径,可以通过运行 `mysql_config --socket` 命令来获取。 ### 回答2: php.ini是PHP的配置文件之一,它用于配置PHP的运行参数和选项。而pdo_mysql.default_socket是php.ini中的一个设置,用于指定PDO使用的MySQL套接字文件的路径。 MySQL套接字文件是MySQL数据库连接的一种方式,通过套接字文件,PHP可以与MySQL进行通信和交互。这个设置允许我们指定套接字文件的路径,以便PHP可以正确地连接到MySQL数据库。 在php.ini文件中,当pdo_mysql.default_socket没有设置时,PHP会尝试使用默认的套接字文件路径。这个默认的路径通常是由MySQL服务器的安装位置确定的。然而,如果MySQL服务器的安装位置不同,或者我们希望使用不同的套接字文件,就需要通过修改php.ini文件来指定pdo_mysql.default_socket的值。 例如,如果我们的MySQL服务器安装在/usr/local/mysql目录下,而默认的套接字文件路径是/tmp/mysql.sock,我们可以通过修改php.ini中的pdo_mysql.default_socket参数来指定新的套接字文件路径,如下所示: pdo_mysql.default_socket = /usr/local/mysql/mysql.sock 这样一来,PHP在连接MySQL数据库时就会使用我们指定的套接字文件路径。 总之,pdo_mysql.default_socket是php.ini中用于指定PDO使用的MySQL套接字文件路径的设置。根据实际需要,我们可以通过修改php.ini文件来设置该值,以确保PHP能够正确地连接到MySQL数据库。 ### 回答3: php.ini是PHP的配置文件,用于配置PHP运行环境的各种参数和选项。其中的pdo_mysql.default_socket是一个用于指定PDO连接MySQL数据库所使用的Unix套接字文件路径的选项。 由于PHP在连接MySQL数据库时,默认使用的是MySQL的TCP/IP协议进行通信,所以pdo_mysql.default_socket选项默认为空。这种情况下,PHP通过TCP/IP连接MySQL数据库,在连接字符串中指定MySQL服务器的IP地址和端口号。 如果想要使用Unix套接字文件进行连接,可以通过修改php.ini文件中pdo_mysql.default_socket的值来实现。例如,可以将pdo_mysql.default_socket的值设置为"/tmp/mysql.sock",表示连接MySQL数据库的时候使用套接字文件"/tmp/mysql.sock"。 使用Unix套接字文件连接MySQL数据库相对于TCP/IP连接有一些优势,如更快的速度、更高的安全性和更少的资源占用。因此,在某些情况下,使用Unix套接字文件连接MySQL数据库可能会更加适用。 需要注意的是,修改php.ini文件后,需要重启Web服务器或者PHP-FPM才能使修改生效。此外,还可以在代码中使用ini_set()函数来修改pdo_mysql.default_socket的值,在连接MySQL数据库之前进行动态配置。 综上所述,pdo_mysql.default_socket是用于指定PDO连接MySQL数据库所使用的Unix套接字文件路径的选项,在需要使用Unix套接字文件进行连接时,可以通过修改php.ini文件中的该选项的值来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值