开发文档 v2.x

快速批量更新(quickUpdateMany)

更新时间:2022年8月27日 02:27 浏览:43

快速批量更新多个对象或数组到数据库

public function quickUpdateMany(string $table, array $objects, $primaryKey = null): int

参数:

  • string $table - 表名
  • array $objects - 要插入数据库的对象数组或二维数组,对象属性或数组锓名需要和该表字段一致
  • null | string | array $primaryKey 主键或指定键名更新,未指定时自动取表的主键

返回值:

  • int - 更新的行数,如果数据无变化,则返回0,更新失败时抛出异常

 

快速批量更新方法没有预先编译 SQL 横板,而是直接生成 SQL,但插入的数据会通过 PDO 提供的 quote 方法处理 防止注入。

因为少了编译 SQL 的步骤,快速批量更新方法执行速度更快。MYSQL原生不支持快速批量更新,底层使用 case when 实现。更新的字段和行数较多时,最终生成的SQL语句长度会指数级快速增长,MYSQL解析时间会变长,实际项目中跟据具体情况调整,一般几百条执行时是比较划算的。

如果更新条件是主键或唯一键,且数据库为 MySQL时,更好的方案是用 替换 章节下的 快速批量替换(quickReplaceMany)

 

对象数组形式:

$objs = [];

$obj1 = new stdClass();
$obj1->id = 'cf8ee5b8-9b8f-11ec-9b24-0242ac180065';
$obj1->name = '马云';
$obj1->age = 51;
$objs[] = $obj1;

$obj2 = new stdClass();
$obj1->id = 'd8c5844c-9e12-11ec-a3cb-0242ac180065';
$obj2->name = '刘强东';
$obj1->age = 41;
$objs[] = $obj2;

// 更多对象 ... 

$effectRows = Be::getDb()->quickUpdateMany('user', $objs);

将执行 SQL

UPDATE
    `user`
SET 
    `name` = CASE `id` 
        WHEN 'cf8ee5b8-9b8f-11ec-9b24-0242ac180065' THEN '马云' 
        WHEN 'd8c5844c-9e12-11ec-a3cb-0242ac180065' THEN '刘强东' 
    END,
    `age` = CASE `id` 
        WHEN 'cf8ee5b8-9b8f-11ec-9b24-0242ac180065' THEN 51
        WHEN 'd8c5844c-9e12-11ec-a3cb-0242ac180065' THEN 41 
    END
WHERE
    `id` IN (
        'cf8ee5b8-9b8f-11ec-9b24-0242ac180065', 
        'd8c5844c-9e12-11ec-a3cb-0242ac180065'
    )


 

二维数组形式:

$arrs = [
    [
        'id' =>  'cf8ee5b8-9b8f-11ec-9b24-0242ac180065',
        'name' => '马云',
    ],
    [
        'id' =>  'd8c5844c-9e12-11ec-a3cb-0242ac180065',
        'name' => '刘强东',
    ]
];

$effectRows = Be::getDb()->quickIUpdateMany('user', $arrs);

 

按非主键更新

$objs = [];

$obj1 = new stdClass();
$obj1->name = '马云';
$obj1->age = 51;
$objs[] = $obj1;

$obj2 = new stdClass();
$obj2->name = '刘强东';
$obj1->age = 41;
$objs[] = $obj2;

// 更多对象 ... 

$effectRows = Be::getDb()->quickUpdateMany('user', $objs, 'name');

将执行 SQL

UPDATE
    `user`
SET 
    `age` = CASE `name` 
        WHEN '马云' THEN 51
        WHEN '刘强东' THEN 41 
    END
WHERE
    `name` IN (
        '马云', 
        '刘强东'
    )

 

按多个非主键更新

$objs = [];

$obj1 = new stdClass();
$obj1->name = '马云';
$obj1->age = 51;
$obj1->sex = '男';
$objs[] = $obj1;

$obj2 = new stdClass();
$obj2->name = '刘强东';
$obj1->age = 41;
$obj1->sex = '男';
$objs[] = $obj2;

// 更多对象 ... 

$effectRows = Be::getDb()->quickUpdateMany('user', $objs, ['name', 'sex']);

将执行 SQL

UPDATE
    `user`
SET 
    `age` = CASE 
        WHEN `name`= '马云' AND `sex`='男' THEN 51
        WHEN `name`='刘强东' AND `sex`='男' THEN 41 
    END
WHERE
    (`name`, `sex`) IN (
        ('马云', '男'),
        ('刘强东', '男')
    )

 

导航