Laravel插入或更新多行

时间:2016-11-29 10:06:36

标签: laravel insert rows

我是laravel的新手,我试图更新我的导航树。 所以我想在没有foreach的情况下在一个查询中更新我的整个树。

array(
  array('id'=>1, 'name'=>'some navigation point', 'parent'='0'),
  array('id'=>2, 'name'=>'some navigation point', 'parent'='1'),
  array('id'=>3, 'name'=>'some navigation point', 'parent'='1')
);

我只是想问一下 - 在laravel中是否可以插入(如果是数组中的新数据)或更新我在数据库中的当前行?

我想更新所有,因为我在我的树中有字段_lft,_right,parent_id,我使用一些可拖动的js插件来设置我的导航结构 - 现在我想保存它。

我尝试使用

Navigation::updateOrCreate(array(array('id' => '3'), array('id'=>'4')), array(array('name' => 'test11'), array('name' => 'test22')));

但它只适用于单行,而不是像我试图做的那样多行。 也许有另一种方法可以做到这一点?

7 个答案:

答案 0 :(得分:6)

我想知道为什么Laravel核心中还没有这种功能(直到今天)。查看this gist查询字符串的结果如下所示:here

我将代码放在这里以防万一以后链接中断,我不是作者:

/**
* Mass (bulk) insert or update on duplicate for Laravel 4/5
* 
* insertOrUpdate([
*   ['id'=>1,'value'=>10],
*   ['id'=>2,'value'=>60]
* ]);
* 
*
* @param array $rows
*/
function insertOrUpdate(array $rows){
    $table = \DB::getTablePrefix().with(new self)->getTable();


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

因此,您可以安全地将数组插入或更新为:

insertOrUpdate(
    array(
      array('id'=>1, 'name'=>'some navigation point', 'parent'='0'),
      array('id'=>2, 'name'=>'some navigation point', 'parent'='1'),
      array('id'=>3, 'name'=>'some navigation point', 'parent'='1')
    )
);

如果函数中第一行出现任何问题,您只需添加一个表名作为第二个参数,然后注释掉该行,即:

function insertOrUpdate(array $rows, $table){
    .....
}

insertOrUpdate(myarrays,'MyTableName');
  

注意:虽然要小心你的输入,但要小心!并记住没有触及时间戳字段。你可以通过手动添加到主数组中的每个数组来实现。

答案 1 :(得分:5)

现在可以在 Laravel >= 8.x

<块引用>

该方法的第一个参数包含要插入或更新的值,而第二个参数列出唯一标识关联表中记录的列。该方法的第三个也是最后一个参数是一个列数组,如果数据库中已存在匹配的记录,则应更新该数组:

Flight::upsert([
    ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
    ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], ['departure', 'destination'], ['price']);

答案 2 :(得分:2)

口才的风格

public function meta(){ // in parent models.
    return $this->hasMany('App\Models\DB_CHILD', 'fk_id','local_fk_id');
}

。 。

$parent= PARENT_DB::findOrFail($id);
$metaData= [];
        foreach ($meta['meta'] as $metaKey => $metaValue) {

            if ($parent->meta()->where([['meta_key', '=',$metaKey]] )->exists()) { 
                $parent->meta()->where([['meta_key', '=',$metaKey]])->update(['meta_value' => $metaValue]);
            }else{
                $metaData[] = [
                    'FK_ID'=>$fkId,
                    'meta_key'=>$metaKey,
                    'meta_value'=> $metaValue
                ];
            }

        }
$Member->meta()->insert($metaData);

答案 3 :(得分:0)

不,你不能这样做。您可以一次insert()多行,并且可以使用相同update()条件where()多行,但如果您想使用updateOrCreate(),则需要使用foreach()循环。

答案 4 :(得分:0)

在您的控制器中  使用DB;         公共职能arrDta(){

        $up_or_create_data=array(
            array('id'=>2, 'name'=>'test11'),
            array('id'=>4, 'name'=>'test22')

        );

        var_dump($up_or_create_data);
        echo "fjsdhg";

        foreach ($up_or_create_data as $key => $value) {
            echo "key  ".$key;
            echo "<br>";
            echo " id: ".$up_or_create_data[$key]["id"];
            echo "<br>";
            echo " Name: ".$up_or_create_data[$key]["name"];


        if (Navigation::where('id', '=',$up_or_create_data[$key]["id"])->exists()) {
            DB::table('your_table_ name')->where('id',$up_or_create_data[$key]["id"])->update(['name' => $up_or_create_data[$key]["name"]]);
        }else{
            DB::insert('insert into your_table_name (id, name) values (?, ?)', [$up_or_create_data[$key]["id"], $up_or_create_data[$key]["name"]]);
        }

        }

答案 5 :(得分:0)

我为所有数据库创建了一个UPSERT软件包:https://github.com/staudenmeir/laravel-upsert

componentWillMount() {
    fetch('http://localhost:3000/product/4317892')
        .then(res => res.json())
        .then(res => {
            this.setState({
                ...this.state, // Not required but just a heads up on using mutation
                posts: res
            })
        })
        .catch((error => {
            console.error(error);
        }));
}


render() {
    console.log(this.state)
    return (
        <div>
            <p><strong>Id: {this.state.posts.IDPRODUCT}</strong></p>
            <p>Description: {this.state.posts.DESCRIPTION}</p>
        </div>
    );
}

答案 6 :(得分:0)

我找不到在一个查询中批量插入或更新的方法。但是我只处理了3个查询。我有一个表名shipping_costs。在这里,我想针对运输区域更新运输成本。在此表中,我只有5列ID,area_id,cost,created_at,updated_at。

// first get ids from table
$exist_ids = DB::table('shipping_costs')->pluck('area_id')->toArray();
// get requested ids
$requested_ids = $request->get('area_ids');
// get updatable ids
$updatable_ids = array_values(array_intersect($exist_ids, $requested_ids));
// get insertable ids
$insertable_ids = array_values(array_diff($requested_ids, $exist_ids));
// prepare data for insert
$data = collect();
foreach ($insertable_ids as $id) {
$data->push([
    'area_id' => $id,
    'cost' => $request->get('cost'),
    'created_at' => now(),
    'updated_at' => now()
]);
}
DB::table('shipping_costs')->insert($data->toArray());

// prepare for update
DB::table('shipping_costs')
->whereIn('area_id', $updatable_ids)
->update([
    'cost' => $request->get('cost'),
    'updated_at' => now()
]);