php pdo中PDOStatement 类的bindParam和bindValue方法的区别

在PDOStatement 类中两种方法的具体说明如下

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

区别1:bindParam是绑定一个参数到指定的变量名,bindValue则是把一个值绑定到一个参数

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');
$st = $db->prepare('select * from tabletest where id = ?');
$id = 1;
$st->bindParam(1,$id,PDO::PARAM_INT);
//$st->bindValue(1,$id,PDO::PARAM_INT);
 在上述代码中,不管是bindParam或者bindValue,都能够正常执行,但是如果换成如下代码 

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');
$st = $db->prepare('select * from tabletest where id = ?');
$st->bindParam(1,1,PDO::PARAM_INT);
//$st->bindValue(1,1,PDO::PARAM_INT);

bindParam就会报如下错误,但是bindValue却可以正常执行

Fatal error: Cannot pass parameter 2 by reference
总结:bindParam第二个参数有且只能是一个变量名, 不能是一个具体的值,bindValue既可以绑定一个变量名,又可以绑定一个值

区别2:不同于 PDOStatement::bindValue(),PDOStatement::bindParam()中的变量作为引用被绑定,并只在 PDOStatement::execute() 被调用的时候才取其值

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');
$st = $db->prepare('select * from tabletest where id = ?');
$id = 1;
$st->bindParam(1,$id,PDO::PARAM_INT);
$id = 2;
$st->execute();
$rs = $st->fetchAll();
print_r($rs);
首先给$id赋值为1,bindParam绑定变量,在execute前,更改$id为2,然后进行执行操作,此时获得的结果集是当id=2的时候的查询结果,并非是id为1时的查询结果,这就是变量作为引用的解释,在execute之前,我们可以对此变量进行替换,而执行execute操作时候代入的变量值,是该变量最后一次更改的值。

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');
$st = $db->prepare('select * from tabletest where id = ?');
$id = 1;
$st->bindValue(1,$id,PDO::PARAM_INT);
$id = 2;
$st->execute();
$rs = $st->fetchAll();
print_r($rs);

而bindValue则不同,在使用bindValue绑定变量后,即使在执行execute之前改变了该变量的值,那么结果也不会变。例如上例中即使我们把$id改为了2,但是最后执行的结果仍然会输出$id =1时候的结果,因为bindValue绑定的并非是变量的引用,不会随着变量的更改而更改。

虽然两者都能完成sql参数的绑定,但是两者仍然有区别,在实际应用中,我们应该选择适合我们的,下面举一个bindParam使用不当的例子

假设有一个数据表有整形id和字符串型name两个字段,有一数组数据$params = array(1,'张三')准备使用预处理进行插入,具体代码如下

$db = new PDO('mysql:host=localhost;dbname=dbtest;charset=utf8','user','pass');
$st = $db->prepare('insert into tabletest(id,name) values(?,?)');
$params = array(1,'张三');
foreach($params as $k => $v){
    $index = $k + 1;
    $st->bindParam($index,$v);
}
$st->execute();
正常情况被执行的sql语句应该是

insert into tabletest(id,name) values(1,'张三');
其实真正执行的sql语句却是

insert into tabletest(id,name) values('男','男');

究其原因就是bindParam中的变量作为了引用被绑定,因此最后每个字段插入的数值都变成了最后一个字段的值,而此时我们使用bindValue就不会出现这种问题了。此例中还有一点需要说明的是如果使用的是问号占位符和索引数组结合,特别需要注意bindValue的参数标识符(该方法的第一个参数),索引数组默认从0开始,而bindValue的参数标识符是以1开始,如果直接套入索引数组的0下标,那么程序就会报错,使用的时候一定需要注意。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值