BatchUpdateTrait.php 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. <?php
  2. namespace App\Libs;
  3. use Illuminate\Support\Facades\DB;
  4. trait BatchUpdateTrait
  5. {
  6. /**
  7. * @param string $table
  8. * @param array $list_data
  9. * @param string $index
  10. * @param int $chunk_size
  11. *
  12. * @return int
  13. */
  14. public function batchUpdateDb(string $table, array $list_data, string $index = 'id', int $chunk_size = 500): int
  15. {
  16. if (count($list_data) < 1 || $chunk_size < 1) {
  17. return 0;
  18. }
  19. $chunk_list = array_chunk($list_data, $chunk_size);
  20. $count = 0;
  21. foreach ($chunk_list as $list_item) {
  22. $first_row = current($list_item);
  23. $update_col = array_keys($first_row);
  24. // 默认以id为条件更新,如果没有ID则以第一个字段为条件
  25. $reference_col = isset($first_row[$index]) ? $index : current($update_col);
  26. unset($update_col[0]);
  27. // 拼接sql语句
  28. $update_sql = 'UPDATE ' . $table . ' SET ';
  29. $sets = [];
  30. $bindings = [];
  31. foreach ($update_col as $u_col) {
  32. $set_sql = '`' . $u_col . '` = CASE ';
  33. foreach ($list_item as $item) {
  34. $set_sql .= 'WHEN `' . $reference_col . '` = ? THEN ';
  35. $bindings[] = $item[$reference_col];
  36. if ($item[$u_col] instanceof \Illuminate\Database\Query\Expression) {
  37. $set_sql .= $item[$u_col]->getValue() . ' ';
  38. } else {
  39. $set_sql .= '? ';
  40. $bindings[] = $item[$u_col];
  41. }
  42. }
  43. $set_sql .= 'ELSE `' . $u_col . '` END ';
  44. $sets[] = $set_sql;
  45. }
  46. $update_sql .= implode(', ', $sets);
  47. $where_in = collect($list_item)->pluck($reference_col)->values()->all();
  48. $bindings = array_merge($bindings, $where_in);
  49. $where_in = rtrim(str_repeat('?,', count($where_in)), ',');
  50. $update_sql = rtrim($update_sql, ', ') . ' WHERE `' . $reference_col . '` IN (' . $where_in . ')';
  51. //
  52. $count += DB::update($update_sql, $bindings);
  53. }
  54. return $count;
  55. }
  56. }