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

方案选择

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

1、逐条更新

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

2、CASE WHEN

  类似如下的语句

    , );

PDO绑定参数

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

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

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

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

修改后的写法:

 <?php
          $data = array(array('id' => 1, 'val' => 2), array('id' => 2, 'val' => 3));
          $update_sql = 'UPDATE tbl_test SET val = CASE id';
          $params = array();
          $params[":ids"] = $ids;
          $in_arr = array();

          foreach($data as $key => $item) {
                  $update_sql .= "WHEN :id_" . $key . "THEN :val_" . $key . " ";
                  $params[":id_" . $key] = $item['id'];
                  $params[":val_" . $key] = $item['val'];
                  $params[":ids_" . $key] = $item['id'];
                  array_push($in_arr, ":id_" . $key);
          }
          $update_sql .= "END WHERE id IN (" . implode(',' $in_arr) . ")";
          TEST::execute($update_sql, $params);//此处会调用bindParam绑定参数

总结

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

参考链接:

mysql语句:批量更新多条记录的不同值

Can I bind an array to an IN() condition?

原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

如果本文对你有帮助,请点下推荐,写文章不容易。

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

  1. Pdo 绑定参数方法 通用更新语句

    public  static  function upShelf($table,$arr,$where)    { //将传入的数组进行key vlaue 分离 并将key值以问号方式绑定参数     ...

  2. Yii 1.1 DAO绑定参数实例

    <?php $sql = "SELECT * FROM admin_user WHERE user_name=:uname AND password LIKE :c"; $c ...

  3. [猜你喜欢]冠军“yes,boy!”分享,含竞赛源代

    [猜你喜欢]冠军“yes,boy!”分享,含竞赛源代码  DataCastle运营 发表于 2016-7-20 17:31:52      844  3  5 我是Yes,boy! ,来自东北大学计算 ...

  4. 图像显示 imshow()[OpenCV 笔记5]

    void imshow(const string& winname InputArray mat); winname 窗口表识名称 mat 需要显示的图像.InputArray类型,声明如下 ...

  5. Hibernate绑定参数

    使用绑定参数的优势: 我们为什么要使用绑定命名参数?任何一个事物的存在都是有其价值的,具体到绑定参数对于HQL查询来说,主要有以下两个主要优势:①. 可以利用数据库实施性能优化 因为对Hibernat ...

  6. thinkphp5.0学习笔记(三)获取信息,变量,绑定参数

    1.构造函数: 控制器类必须继承了\think\Controller类,才能使用: 方法_initialize 代码: <?php namespace app\lian\controller; ...

  7. [转载]mysql绑定参数bind_param原理以及防SQL注入

    假设我们的用户表中存在一行.用户名字段为username.值为aaa.密码字段为pwd.值为pwd.. 下面我们来模拟一个用户登录的过程.. <?php $username = "aa ...

  8. mysql绑定参数bind_param原理以及防SQL注入

    假设我们的用户表中存在一行.用户名字段为username.值为aaa.密码字段为pwd.值为pwd.. 下面我们来模拟一个用户登录的过程.. <?php $username = "aa ...

  9. SpringMVC中,前台jsp封装参数,绑定参数,传递参数到后台controller的过程详解

    前台到后台的流程:前台jsp->后台:controller控制器层->service业务层->DAO数据访问层->数据库model模型层. 从上面流程可知,前台jsp的数据,想 ...

随机推荐

  1. Log4net快速索引参考

    官方项目地址:The Apache log4net project 本文内容仅为相关项参考,不进行具体使用讨论 另转载请注明出处 Log4net快速索引参考 Log4net主要有以下三个部件: log ...

  2. WPF时间格式化

    日期格式化示例: <TextBox  Name="txtCreateTime" HorizontalAlignment="Left" Width=&quo ...

  3. java中包的命令行(cmd)操作详解

    一.什么是包? 为了更好地组织类,防止在一个空间下出现类重名,Java提供了包机制.包是类的容器,用于分隔类名空间(类型于C++中的命名空间).如果没有指定包名,所有的示例都属于一个默认的无名包(又称 ...

  4. npm淘宝镜像cnpm

    npm install -g cnpm --registry=https://registry.npm.taobao.org

  5. Hello, cnblogs !

    来博客园的第一天. 大学毕业三年多了,感觉自己碌碌无为,不知道自己究竟想做什么,就这样浑浑噩噩过了三年多. 记得大三那年,为了准备大四的毕业设计,自学了好几个月的Java EE.Java基础.Java ...

  6. iOS how to stop a scrolling scrollView

    - (void)killScroll { CGPoint offset = scrollView.contentOffset; offset.y -= 1.0; [scrollView setCont ...

  7. 配置gradle.properties

    在一些项目中会分拆app 和 lib , 这时候引用support的时候,一旦更改版本会出现需要同步更改两个地方的问题.这种情况,可以通过配置gradle.properties实现替换. 在项目编译过 ...

  8. 数据库访问性能优化 Oracle

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

  9. [R]R语言中的%>%和%.%

    最近在网上看R的代码,常常看到 x %>% y 的写法. 样子看着像是pipe的用法,搜了一下, 没找到语法的相关说明. 今天突然开窍,想着 %>% 可能不是语言本身支持的语法,可能是某个 ...

  10. img只显示图片一部分 或 css设置背景图片只显示图片指定区域

    17:14 2016/3/22img只显示图片一部分 或 css设置背景图片只显示图片指定区域 background-position: 100% 56%; 设置背景图片显示图片的哪个坐标区域,图片左 ...