当前位置: 首页 > 后端技术 > PHP

PHP批量更新

时间:2023-03-29 22:18:10 PHP

mysql更新语句很简单,更新一条数据的某个字段,一般这样写:UPDATEmytableSETmyfield='value'WHEREother_field='other_value';如果同一个字段更新为同一个值,mysql也很简单,修改where即可:UPDATEmytableSETmyfield='value'WHEREother_fieldin('other_values');这里注意other_values是用逗号分隔的字符串,比如:1,2,31如果常规方案要更新多条不同值的数据,很多人可能会这样写:foreach($display_orderas$id=>$ordinal){$sql="UPDATEcategoriesSETdisplay_order=$ordinalWHEREid=$id";mysql_query($sql);}就是循环一条一条的更新记录。一条记录更新一次,性能较差,容易造成阻塞。2高效解决方案那么一条SQL语句是否可以实现批量更新呢?2.1CASEWHENmysql没有提供直接的方法来实现批量更新,但是可以通过一些小技巧来实现。UPDATEmytableSETmyfield=CASEidWHEN1THEN'value'WHEN2THEN'value'WHEN3THEN'value'ENDWHEREidIN(1,2,3)这里使用了casewhen的技巧来实现批量更新。例如:UPDATEcategoriesSETdisplay_order=CASEidWHEN1THEN3WHEN2THEN4WHEN3THEN5ENDWHEREidIN(1,2,3)这个sql的意思是更新display_order字段:ifid=1thendisplay_order的值display_order为3,如果id=2,则display_order的值为4,如果id=3,则display_order的值为5。即条件语句写在一起。这里的where部分不影响代码的执行,但是会提高SQL执行的效率。确保sql语句只执行需要修改的行数。这里只更新了3行数据,where子句保证只执行3行数据。3.2更新多个值如果更新多个值,只需要稍微修改一下:UPDATEcategoriesSETdisplay_order=CASEidWHEN1THEN3WHEN2THEN4WHEN3THEN5END,title=CASEidWHEN1THEN'NewTitle1'WHEN2THEN'NewTitle2'WHEN3THEN'NewTitle3'ENDWHEREidIN(1,2,3)至此,一条mysql语句更新多条记录已经完成。但是要在业务中使用它,需要结合服务器端语言。3.3封装为一个PHP函数在PHP中,我们将这个函数封装成一个函数,后面直接调用。为了提高可用性,我们考虑处理更全面的案例。需要更新以下数据,我们需要根据id和parent_id字段更新post表的内容。其中id的值会变化,parent_id的值不变。$data=[['id'=>1,'parent_id'=>100,'title'=>'A','sort'=>1],['id'=>2,'parent_id'=>100,'title'=>'A','sort'=>3],['id'=>3,'parent_id'=>100,'title'=>'A','sort'=>5],['id'=>4,'parent_id'=>100,'title'=>'B','sort'=>7],['id'=>5,'parent_id'=>101,'title'=>'A','排序'=>9],];比如我们要根据不同的id批量更新parent_id为100、title为A的记录:echobatchUpdate($data,'id',['parent_id'=>100,'title'=>'A']);其中,batchUpdate()实现的PHP代码如下:/***批量更新函数*@param$dataarray待更新数据,二维数组格式*@paramarray$paramsarray条件相同value,key值对应的一维数组*@paramstring$fieldstring不同value的条件,默认为id*@returnbool|string*/functionbatchUpdate($data,$field,$params=[]){如果(!is_array($data)||!$field||!is_array($params)){returnfalse;}$updates=parseUpdate($data,$field);$where=解析参数($params);//获取key名称为$field列的所有值,在值两边加上单引号,保存在$fields数组中//array_column()函数需要PHP5.5.0+,如果低于这个版本,可以自己实现,//参考地址:http://php.net/manual/zh/function.array-column.php#118831$fields=array_column($data,$field);$fields=implode(',',array_map(function($value){return"'".$value."'";},$fields));$sql=sprintf("UPDATE`%s`SET%sWHERE`%s`IN(%s)%s",'post',$updates,$field,$fields,$where);return$sql;}/***转换二维将数组转换为CASEWHENTHEN的批量更新条件*@param$dataarray二维数组*@param$fieldstring列名*@returnstringsql语句*/函数parseUpdate($data,$field){$sql='';$keys=array_keys(current($data));foreach($keysas$column){$sql.=sprintf("`%s`=CASE`%s`\n",$column,$field);foreach($dataas$line){$sql.=sprintf("WHEN'%s'THEN'%s'\n",$line[$field],$line[$column]);}$sql.="结束,";}returnrtrim($sql,',');}/***解析where条件*@param$params*@returnarray|string*/functionparseParams($params){$where=[];foreach($paramsas$key=>$value){$where[]=sprintf("`%s`='%s'",$key,$value);返回$where?'和'。implode('AND',$where):'';}获取这样一条批量更新SQL语句:UPDATE`post`SET`id`=CASE`id`WHEN'1'THEN'1'WHEN'2'THEN'2'当'3'然后'3'当'4'然后'4'当'5'然后'5'结束时,`parent_id`=CASE'id`当'1'然后'100'当'2'然后'100'当'3'然后'100'当'4'然后'100'当'5'然后'101'结束时,`title`=CASE`id`当'1'然后'A'当'2'然后'A'当'3'然后'A'当'4'然后'B'当'5'然后'A'结束时,`sort`=CASE`id`当'1'然后'1'当'2'然后'3'当'3'然后'5'当'4'然后'7'当'5'然后'9'结束时'id'在('1','2','3','4','5')AND`parent_id`='100'AND`title`='A'生成的SQL列出了所有的情况,但是由于WHERE条件有限,只更新了ids为1、2、3的几条记录。如果只需要更新某列,不限制其他条件,那么传入的$data可以更简单:$data=[['id'=>1,'sort'=>1],['id'=>2,'排序'=>3],['id'=>3,'排序'=>5],];echobatchUpdate($data,'id');如果传入这样的数据格式,id可以修改为1~3条记录,将sort分别改为1、3、5。获取SQL语句:UPDATE`post`SET`id`=CASE`id`WHEN'1'THEN'1'WHEN'2'THEN'2'WHEN'3'THEN'3'END,`sort`=CASE`id`WHEN'1'THEN'1'WHEN'2'THEN'3'WHEN'3'THEN'5'ENDWHERE`id`IN('1','2','3')更简单高效.