web-dev-qa-db-ja.com

laravel重複したキーを挿入するときの雄弁な無視エラー

別のサービスからJSONをフェッチしていて、大量のデータをテーブルに挿入したい。実行するたびにクラッシュしないようにしたいのですが。テーブルのPKに固有の制約を保持したい(同じデータを2回挿入したくないため)が、laravelで致命的なエラーをスローしたくない発生した場合(特定のテーブルのみ)。

データを挿入し、重複する主キーを持つ別のデータを挿入しようとした場合、挿入を続行するにはどうすればよいですか?

Schema::create('dummy', function (Blueprint $table) {
    $table->integer('id')->unique();

    $table->string('name',100);
});

別のAPIから一連のJSONをフェッチします。次に、すべての行を挿入します。

{ 
   'id':1,
    'name': 'one'
},{
    'id':2
    'name':'two'
}

それは作ります。

DB::table('dummy')->insert([
    ['id' => 1, 'name' => 'one'],
    ['id' => 2, 'name' => 'two']
]);

その後、別の日に、サードパーティのAPIに関する新しいデータがあります。そして私のデータベースを更新したい:

jsonをフェッチして受け取ります。

{ 
   'id':1,
    'name': 'one'
},{
    'id':2
    'name':'two'
},{
    'id':3
    'name':'three'
}

それは:

DB::table('dummy')->insert([
    ['id' => 1, 'name' => 'one'], // <-- will crash there cause PK already existe, but want to keep inserting
    ['id' => 2, 'name' => 'two'], // <-- skipp cause already exist
    ['id' => 3, 'name' => 'three'] // insert that line.
]);
11
PL Audet

あなたはPDO例外をキャッチしようとするかもしれません

try 
{
    // inserting in DB;
}
catch(\Illuminate\Database\QueryException $e){
    // do what you want here with $e->getMessage();
}

あるいは、確かではありませんが、DBトランザクションを試すこともできます。

public function insertInDB()
{
    DB::transaction(function () {
        DB::table(...);
        // if everything is fine, it will commit, else, it will rollback
    }
}
4
EddyTheDove

Laravel Query Builderはバージョンv5.8.33以降でinsertOrIgnoreを備えています。

<?php
DB::table('users')->insertOrIgnore([
    ['id' => 1, 'email' => '[email protected]'],
    ['id' => 2, 'email' => '[email protected]']
]);

詳細はこちら: https://laravel.com/docs/5.8/queries#inserts

2
Jared Dunham

あなたが欲しいのはINSERT IGNOREとその質問には既に回答済みです。 Laravelの流暢を使用してINSERT IGNOREを参照してください

0
arecaps