laravel是否具有类似于Codeigniter的更新批处理功能?
Codeigniter使用$this->db->update_batch('mytable', $data, 'title');
进行批量更新。更多信息可以在这里找到。
但对于laravel的更新,它似乎只能做一笔交易。我觉得当你有多行要更新时,这有点糟糕,因为它将在for循环中。类似的东西:
foreach ($rows => $row) {
DB::table('users')->where('id', $row['row_id'])->update(['votes' => 1]);
}
至少你明白了,对吧?
如果你仔细研究一下这段代码,你的数据库可能会被破坏,因为它一直在连接,不像update_batch()
,只有一个事务被抛出。
TL;DR-尚不清楚CodeIgniter(CI)方法是否比一系列UPDATE
查询更高效。此外,CI方法不如UPDATE
s的循环序列清晰。
说Laravel"继续连接"是不正确的——它会在请求开始时打开一个连接,并一直使用该连接,直到请求完成。我认为您的意思是向服务器发送大量查询。
的确,这样做:
INSERT INTO table VALUES (1, ...);
INSERT INTO table VALUES (2, ...);
INSERT INTO table VALUES (3, ...);
...
INSERT INTO table VALUES (n, ...);
会比这样做效率低:
INSERT INTO table VALUES (1, ...),
(2, ...),
(3, ...),
...
(n, ...);
但这并不是一个简单的INSERT
。查看您发布的链接中CI库生成的代码。我们所看到的是之间的效率差异
UPDATE table SET value=1 WHERE id=1;
UPDATE table SET value=2 WHERE id=2;
UPDATE table SET value=3 WHERE id=3;
...
UPDATE table SET value=n WHERE id=n;
和
UPDATE table
SET value = CASE
WHEN id = 1 THEN 1
WHEN id = 2 THEN 2
WHEN id = 3 THEN 3
...
WHEN id = n THEN n
ELSE value END
WHERE id IN (1, 2, 3, ..., n);
我不是SQL专家,但我不相信第二个比第一个更有效率。长链的WHEN
子句将由SQL server处理——在我看来,一堆短的UPDATE
语句将更高效,尤其是当您在WHERE
子句中使用索引列时。
最后,查看CI文档,update_batch
方法对传递给它的数据的结构进行了一些假设,例如,数组中的第一项是更新语句的键。当你在六个月后查看代码时,这一点(至少对我来说)不会很清楚。
也许这将有助于
trait InsertOrUpdate {
static function InsertOrUpdate(array $rows) {
$table = DB::getTablePrefix().with(new self)->getTable();
if (empty($table)) {
return false;
}
$maxRowData = DB::table($table)->where('id', DB::raw('(select max(`id`) from ' . $table . ')'))->first();
if (! empty($maxRowData)) {
$maxId = $maxRowData->id;
$result = DB::statement('ALTER TABLE ' . $table . ' AUTO_INCREMENT = ' . $maxId . ';');
}
$tableColumns = DB::getSchemaBuilder()->getColumnListing($table);
$datetime = Carbon::now()->toDateTimeString();
if (in_array('created_at', $tableColumns)) {
foreach ($rows as $key => $row) {
$rows[$key]['created_at'] = $datetime;
$rows[$key]['updated_at'] = $datetime;
}
}
$first = reset($rows);
$columns = implode(',',
array_map(function($value) {
return "$value";
},
array_keys($first))
);
$values = implode(',', array_map(function($row) {
return '('.implode( ',',
array_map(function($value) { return '"' . str_replace('"', '""', $value) . '"'; }, $row)
).')';
} , $rows)
);
$updates = '';
if (in_array('updated_at', $tableColumns)) {
unset($first['created_at']);
unset($first['updated_at']);
$first['deleted_at'] = NULL;
$updateString = '(CASE WHEN ';
$lastClolumn = count($first);
$columnNum = 1;
foreach (array_keys($first) as $column) {
$updateString .= $column . ' <> VALUES(' . $column . ')';
if ($columnNum != $lastClolumn) {
$updateString .= ' OR ';
}
$columnNum++;
}
$updateString .= ' THEN ''' . $datetime . ''' ELSE `updated_at` END), ';
$updates .= 'updated_at = ' . $updateString;
}
$updates .= implode(',',
array_map(function($value) {return "$value = VALUES($value)"; } , array_keys($first) )
);
$sql = "INSERT INTO {$table}({$columns}) VALUES {$values} ON DUPLICATE KEY UPDATE {$updates};";
return DB::statement($sql);
}
查看数据库事务。。。
https://laravel.com/docs/5.2/database#database-事务