[PDO绑定参数]使用PHP的PDO扩展进行批量更新操作

最近有一个批量更新数据库表中某几个字段的需求,在做这个需求的时候,使用了PDO做参数绑定,其中遇到了一个坑。

方案选择

笔者已知的做批量更新有以下几种方案:

1、逐条更新

  这种是最简单的方案,但无疑也是效率最低的方案。

2、CASE WHEN

  类似如下的语句

UPDATE tbl_test SET val = CASE id WHEN 1 THEN 2 WHEN 2 THEN 3 END WHERE id IN(1, 2);

PDO绑定参数

为了防止SQL注入,使用了PDO扩展绑定参数。上面的数字在一般情况下是变量,那么就需要做参数绑定。刚开始是想着在IN的时候将id组成的字符串作为变量绑定过去,第一次实现的代码如下:

复制代码
 1 <?php
 2         $data = array(array('id' => 1, 'val' => 2), array('id' => 2, 'val' => 3));
 3         $ids = implode(',', array_map(function($v) {return $v['id'];}, $data)); //获取ID数组
 4         $update_sql = 'UPDATE tbl_test SET val = CASE id';
 5         $params = array();
 6         $params[":ids"] = $ids;
 7         foreach($data as $key => $item) {
 8                 $update_sql .= "WHEN :id_" . $key . "THEN :val_" . $key . " ";
 9                 $params[":id_" . $key] = $item['id'];
10                 $params[":val_" . $key] = $item['val'];
11         }
12         $update_sql .= "END WHERE id IN (:_ids)";
13         TEST::execute($update_sql, $params);//此处会调用bindParam绑定参数
复制代码

后来发现这样是行不通的,而且比较诡异的是这样只能更新第一条记录。查阅资料后,发现这样的绑定方式是不行的,IN语句的参数应该一个一个地绑定。看看文档中对bindParam函数的描述:

可以看到,说明里写的是会绑定一个PHP变量到占位符里,所以如果绑定了:ids为1, 2的字符串,那么MySQL解析语句的时候会将1,2解析为单个的变量,而不会当作一串。这也是PDO防SQL注入的原理,通过占位符的绑定,只将绑定的值当作一个值,而不是语句之类的其它东西,这样MySQL只会把传递过去的值当作一个变量的值。

修改后的写法:

复制代码
 1 <?php
 2          $data = array(array('id' => 1, 'val' => 2), array('id' => 2, 'val' => 3));
 3          $update_sql = 'UPDATE tbl_test SET val = CASE id';
 4          $params = array();
 5          $params[":ids"] = $ids;
 6          $in_arr = array();
 7 
 8          foreach($data as $key => $item) {
 9                  $update_sql .= "WHEN :id_" . $key . "THEN :val_" . $key . " ";
10                  $params[":id_" . $key] = $item['id'];
11                  $params[":val_" . $key] = $item['val'];
12                  $params[":ids_" . $key] = $item['id'];
13                  array_push($in_arr, ":id_" . $key);
14          }
15          $update_sql .= "END WHERE id IN (" . implode(',' $in_arr) . ")";
16          TEST::execute($update_sql, $params);//此处会调用bindParam绑定参数
复制代码

 

总结

这是最近遇到的一个小问题,其实更多的是说明在MySQL的IN语句里面做参数绑定时应该一个一个的绑定。

复制代码
src="http://player.youku.com/embed/XNzkxMTc3OTM2" allowfullscreen="" frameborder="0" height="498" width="510">
src="http://player.youku.com/embed/XNzkxMTc3OTM2" allowfullscreen="" frameborder="0" height="498" width="510">

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值