mysql 批量修改

mysql更新语句很简单,更新一条数据的某个字段,一般这样写:

UPDATE mytable SET myfield = ‘value’ WHERE other_field = ‘other_value’;
如果更新同一字段为同一个值,mysql也很简单,修改下
where
即可:

UPDATE mytable SET myfield = ‘value’ WHERE other_field in (‘other_values’);
这里注意,
other_values
是一个逗号

分隔的字符串,如:
1,2,3

那如果是MySQL批量修改不同的记录为不同的值呢?

1 常规方案
那如果修改多条数据为不同的值,可能很多人会这样写:

foreach ($display_order as $id => $ordinal) {
$sql = "UPDATE categories SET display_order = $ordinal WHERE id = i d " ; m y s q l q u e r y ( id"; mysql_query( id";mysqlquery(sql);
}
即是循环一条一条的更新记录。

一条记录
update
一次,这样性能很差,也很容易造成阻塞。

2 高效方案
那么能不能一条sql语句实现批量更新呢?

2.1 CASE WHEN
mysql并没有提供直接的方法来实现批量更新,但是可以用点小技巧来实现。

UPDATE mytable SET
myfield = CASE id
WHEN 1 THEN ‘value’
WHEN 2 THEN ‘value’
WHEN 3 THEN ‘value’
END
WHERE id IN (1,2,3)
这里使用了
case when
这个小技巧来实现批量更新。

举个例子:

UPDATE categories SET
display_order = CASE id
WHEN 1 THEN 3
WHEN 2 THEN 4
WHEN 3 THEN 5
END
WHERE id IN (1,2,3)
这句sql的意思是,更新
display_order
字段:

如果
id=1

display_order
的值为
3

如果
id=2

display_order
的值为
4

如果
id=3

display_order
的值为
5

即是将条件语句写在了一起。

这里的
where
部分不影响代码的执行,但是会提高sql执行的效率。

确保sql语句仅执行需要修改的行数,这里只有
3
条数据进行更新,而
where
子句确保只有
3
行数据执行。

3.2 更新多值
如果更新多个值的话,只需要稍加修改:

UPDATE categories SET
display_order = CASE id
WHEN 1 THEN 3
WHEN 2 THEN 4
WHEN 3 THEN 5
END,
title = CASE id
WHEN 1 THEN ‘New Title 1’
WHEN 2 THEN ‘New Title 2’
WHEN 3 THEN ‘New Title 3’
END
WHERE id IN (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’, ‘sort’ => 9],
];
例如,我们想让
parent_id

100

title

A
的记录依据不同
id
批量更新:

echo batchUpdate($data, ‘id’, [‘parent_id’ => 100, ‘title’ => ‘A’]);
其中,
batchUpdate()
实现的PHP代码如下:

/**

  • 批量更新函数

  • @param $data array 待更新的数据,二维数组格式

  • @param array $params array 值相同的条件,键值对应的一维数组

  • @param string $field string 值不同的条件,默认为id

  • @return bool|string
    */
    function batchUpdate($data, $field, KaTeX parse error: Expected '}', got 'EOF' at end of input: … if (!is_array(data) || ! f i e l d ∣ ∣ ! i s a r r a y ( field || !is_array( field!isarray(params)) {
    return false;
    }

    u p d a t e s = p a r s e U p d a t e ( updates = parseUpdate( updates=parseUpdate(data, $field);
    w h e r e = p a r s e P a r a m s ( where = parseParams( where=parseParams(params);

    // 获取所有键名为 f i e l d 列 的 值 , 值 两 边 加 上 单 引 号 , 保 存 在 field列的值,值两边加上单引号,保存在 fieldfields数组中
    // array_column()函数需要PHP5.5.0+,如果小于这个版本,可以自己实现,

    f i e l d s = a r r a y c o l u m n ( fields = array_column( fields=arraycolumn(data, $field);
    f i e l d s = i m p l o d e ( ′ , ′ , a r r a y m a p ( f u n c t i o n ( fields = implode(',', array_map(function( fields=implode(,,arraymap(function(value) {
    return “’”.$value."’";
    }, $fields));

    $sql = sprintf(“UPDATE %s SET %s WHERE %s IN (%s) %s”, ‘post’, $updates, $field, $fields, $where);

    return $sql;
    }

/**

  • 将二维数组转换成CASE WHEN THEN的批量更新条件

  • @param $data array 二维数组

  • @param $field string 列名

  • @return string sql语句
    */
    function parseUpdate($data, $field)
    {
    $sql = ‘’;
    k e y s = a r r a y k e y s ( c u r r e n t ( keys = array_keys(current( keys=arraykeys(current(data));
    foreach ($keys as $column) {

     $sql .= sprintf("`%s` = CASE `%s` \n", $column, $field);
     foreach ($data as $line) {
         $sql .= sprintf("WHEN '%s' THEN '%s' \n", $line[$field], $line[$column]);
     }
     $sql .= "END,";
    

    }

    return rtrim($sql, ‘,’);
    }

/**

  • 解析where条件

  • @param $params

  • @return array|string
    */
    function parseParams($params)
    {
    w h e r e = [ ] ; f o r e a c h ( where = []; foreach ( where=[];foreach(params as $key => $value) {
    $where[] = sprintf("%s = ‘%s’", $key, $value);
    }

    return $where ? ’ AND ’ . implode(’ AND ', $where) : ‘’;
    }
    得到这样一个批量更新的SQL语句:

UPDATE post SET id = CASE id
WHEN ‘1’ THEN ‘1’
WHEN ‘2’ THEN ‘2’
WHEN ‘3’ THEN ‘3’
WHEN ‘4’ THEN ‘4’
WHEN ‘5’ THEN ‘5’
END,parent_id = CASE id
WHEN ‘1’ THEN ‘100’
WHEN ‘2’ THEN ‘100’
WHEN ‘3’ THEN ‘100’
WHEN ‘4’ THEN ‘100’
WHEN ‘5’ THEN ‘101’
END,title = CASE id
WHEN ‘1’ THEN ‘A’
WHEN ‘2’ THEN ‘A’
WHEN ‘3’ THEN ‘A’
WHEN ‘4’ THEN ‘B’
WHEN ‘5’ THEN ‘A’
END,sort = CASE id
WHEN ‘1’ THEN ‘1’
WHEN ‘2’ THEN ‘3’
WHEN ‘3’ THEN ‘5’
WHEN ‘4’ THEN ‘7’
WHEN ‘5’ THEN ‘9’
END WHERE id IN (‘1’,‘2’,‘3’,‘4’,‘5’) AND parent_id = ‘100’ AND title = ‘A’
生成的SQL把所有的情况都列了出来。

不过因为有
WHERE
限定了条件,所以只有
id

1

2

3
这几条记录被更新。

如果只需要更新某一列,其他条件不限,那么传入的
$data
可以更简单:

d a t a = [ [ ′ i d ′ = > 1 , ′ s o r t ′ = > 1 ] , [ ′ i d ′ = > 2 , ′ s o r t ′ = > 3 ] , [ ′ i d ′ = > 3 , ′ s o r t ′ = > 5 ] , ] ; e c h o b a t c h U p d a t e ( data = [ ['id' => 1, 'sort' => 1], ['id' => 2, 'sort' => 3], ['id' => 3, 'sort' => 5], ]; echo batchUpdate( data=[[id=>1,sort=>1],[id=>2,sort=>3],[id=>3,sort=>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’
END WHERE id IN (‘1’,‘2’,‘3’)
这种情况更加简单高效。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值