Laravel 5.2更新/插入批处理,类似于Codeigniter的update_batch / insert_batch()

时间:2015-12-29 15:02:08

标签: php database codeigniter laravel laravel-5

laravel是否具有类似于Codeigniter的更新批处理功能?

Codeigniter使用$this->db->update_batch('mytable', $data, 'title');进行批量更新。可以找到更多信息here

但至于laravel的update,它似乎只能做一次交易。当你有多行要更新时,我觉得这有点不好,它会在for循环中。类似的东西:

foreach ($rows => $row) {
    DB::table('users')->where('id', $row['row_id'])->update(['votes' => 1]);
}

至少你得到的照片,对吧?

如果您要查看此代码,那么您的数据库可能会因为连续不断而不像update_batch()而被淘汰,只会抛出一个事务。

3 个答案:

答案 0 :(得分:0)

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服务器处理 - 一些简短的UPDATE语句(在我看来)会更高效,特别是当你使用索引时WHERE子句中的列。

最后,在查看CI文档时,update_batch方法会对传递给它的数据结构做出一些假设 - 例如,数组中的第一项是更新语句的关键。当你在六个月后查看你的代码时,(至少对我来说)这一点并不清楚。

答案 1 :(得分:0)

也许会有所帮助

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);
}

答案 2 :(得分:-2)

相关问题