웅변 ORM을 사용하여 라 라벨에 대량 삽입


156

Eloquent ORM을 사용하여 Laravel에서 대량 데이터베이스 삽입을 어떻게 수행 할 수 있습니까?

Laravel 에서이 작업을 수행하려고합니다 : https : //.com/a/10615821/600516 그러나 다음 오류가 발생합니다.

SQLSTATE [HY093] : 유효하지 않은 매개 변수 번호 : 혼합 된 이름 지정된 매개 변수 및 위치 매개 변수.


1
당신은이 있습니까 has_many당신의 모델에서 관계를?
PapaSmurf

1
@jonathandey 아니오 나는 지금 어떤 관계도하지 않습니다
phoenixwizard

@DavidBarker 나는 for 루프를 사용하여 quesr 문자열을 형성하려고 시도했습니다. 나는 laravel에서 트랜잭션을 사용해 보았습니다.
phoenixwizard

@AramBhusal 코드를 게시 할 수 있습니까? 도움이 될만한 코드가 여기에 있습니다.
David Barker

답변:


302

당신은 그냥 사용할 수 있습니다 Eloquent::insert().

예를 들면 다음과 같습니다.

$data = array(
    array('name'=>'Coder 1', 'rep'=>'4096'),
    array('name'=>'Coder 2', 'rep'=>'2048'),
    //...
);

Coder::insert($data);

2
이것은 여전히 ​​라 라벨 4에도 적용됩니까?
advait

4
@advait : 예, 여전히 Laravel 4에 적용됩니다.
Ola

37
Eloquent실제로 접촉하지 않는다는 점에 주목할 가치가 있습니다. Query\Builder@insert()메소드 호출을 프록시합니다 . Eloquent를 사용하여 여러 행을 효율적으로 삽입하는 방법은 없으며 대량 삽입 방법도 제공하지 않습니다.
Jarek Tkaczyk

6
@CanVural 타임 스탬프도 업데이트 / 생성하려면 어떻게해야합니까?
Milan Maharjan

3
이것은 하나의 인서트를 사용합니다. 따라서 충분히 큰 배열이 있으면 실패합니다.
patrox

72

타임 스탬프를 쉽게 업데이트하기 위해 GTF 답변을 업데이트 할 수 있습니다

$data = array(
    array(
        'name'=>'Coder 1', 'rep'=>'4096',
        'created_at'=>date('Y-m-d H:i:s'),
        'modified_at'=> date('Y-m-d H:i:s')
       ),
    array(
         'name'=>'Coder 2', 'rep'=>'2048',
         'created_at'=>date('Y-m-d H:i:s'),
         'modified_at'=> date('Y-m-d H:i:s')
       ),
    //...
);

Coder::insert($data);

업데이트 : @Pedro Moreira가 제안한대로 탄소를 사용할 수있는 날짜를 단순화하기 위해

$now = Carbon::now('utc')->toDateTimeString();
$data = array(
    array(
        'name'=>'Coder 1', 'rep'=>'4096',
        'created_at'=> $now,
        'modified_at'=> $now
       ),
    array(
         'name'=>'Coder 2', 'rep'=>'2048',
         'created_at'=> $now,
         'modified_at'=> $now
       ),
    //...
);

Coder::insert($data);

업데이트 2 : laravel 5 updated_at대신에 사용하십시오.modified_at

$now = Carbon::now('utc')->toDateTimeString();
$data = array(
    array(
        'name'=>'Coder 1', 'rep'=>'4096',
        'created_at'=> $now,
        'updated_at'=> $now
       ),
    array(
         'name'=>'Coder 2', 'rep'=>'2048',
         'created_at'=> $now,
         'updated_at'=> $now
       ),
    //...
);

Coder::insert($data);

42
또는 스크립트 시작 부분에서 Carbon을 사용하여 $now변수 를 정의 하십시오 $now = Carbon::now('utc')->toDateTimeString();. 그런 다음 'created_at' => $now, 'updated_at' => $now모든 삽입에 사용하십시오.
Pedro Moreira

2
새로 삽입 된 행의 모든 ​​ID를 어떻게 얻을 수 있습니까?
akshaykumar6

2
왜 'utc'입니까? 그것은 프로젝트의 선호입니까, 아니면 웅변은 항상 'utc'에서 작동합니까?
pilat

6
거대한 "spaces vs. tabs"인수를 시작하고 싶지 않지만 UTC로 타임 스탬프를 저장하십시오! 나중에 큰 고통을 덜어 줄 것입니다! 전 세계 사용자에 대해 생각하십시오 :)
iSS

2
내가 요청할 수 있다면, Carbon이 상황에서 무엇이 가장 필요한가 ? 무슨 일이야 date("Y-m-d H:i:s")?
Ifedi Okonkwo

30

이것을 읽는 사람은 createMany()method를 확인하십시오 .

/**
 * Create a Collection of new instances of the related model.
 *
 * @param  array  $records
 * @return \Illuminate\Database\Eloquent\Collection
 */
public function createMany(array $records)
{
    $instances = $this->related->newCollection();

    foreach ($records as $record) {
        $instances->push($this->create($record));
    }

    return $instances;
}

28
이것은 대량 삽입이 아닙니다. 구현이 좋지 않기 때문에이 함수는 Item 당 동일한 쿼리를 준비하고 실행합니다.
Paul Spiegel

이것이 관계 메소드라는 점은 주목할 가치가 있습니다 Model::createMany(). 즉 모델에서 직접 호출 할 수는 없습니다 .
5

24

이것이 당신이 좀 더 Eloquent 방식으로하는 방법입니다.

    $allintests = [];
    foreach($intersts as $item){ //$intersts array contains input data
        $intestcat = new User_Category();
        $intestcat->memberid = $item->memberid;
        $intestcat->catid= $item->catid;
        $allintests[] = $intestcat->attributesToArray();
    }
    User_Category::insert($allintests);

3

나는 그것을 여러 번 검색했으며 마침내 timestamps다음과 같이 사용자 정의를 사용했습니다 .

$now = Carbon::now()->toDateTimeString();
Model::insert([
    ['name'=>'Foo', 'created_at'=>$now, 'updated_at'=>$now],
    ['name'=>'Bar', 'created_at'=>$now, 'updated_at'=>$now],
    ['name'=>'Baz', 'created_at'=>$now, 'updated_at'=>$now],
    ..................................
]);

2

Eloquent::insert 올바른 솔루션이지만 타임 스탬프를 업데이트하지 않으므로 다음과 같이 할 수 있습니다

 $json_array=array_map(function ($a) { 
                        return array_merge($a,['created_at'=> 
                                            Carbon::now(),'updated_at'=> Carbon::now()]
                                           ); 
                                     }, $json_array); 
 Model::insert($json_array);

아이디어는 삽입하기 전에 전체 배열에 created_at 및 updated_at를 추가하는 것입니다


0

Laravel 5.7부터 Illuminate\Database\Query\BuilderinsertUsing 메소드를 사용할 수 있습니다.

$query = [];
foreach($oXML->results->item->item as $oEntry){
    $date = date("Y-m-d H:i:s")
    $query[] = "('{$oEntry->firstname}', '{$oEntry->lastname}', '{$date}')";
}

Builder::insertUsing(['first_name', 'last_name', 'date_added'], implode(', ', $query));

-1
$start_date = date('Y-m-d h:m:s');        
        $end_date = date('Y-m-d h:m:s', strtotime($start_date . "+".$userSubscription['duration']." months") );
        $user_subscription_array = array(
          array(
            'user_id' => $request->input('user_id'),
            'user_subscription_plan_id' => $request->input('subscription_plan_id'),
            'name' => $userSubscription['name'],
            'description' => $userSubscription['description'],
            'duration' => $userSubscription['duration'],
            'start_datetime' => $start_date,
            'end_datetime' => $end_date,
            'amount' => $userSubscription['amount'],
            'invoice_id' => '',
            'transection_datetime' => '',
            'created_by' => '1',
            'status_id' => '1', ),
array(
            'user_id' => $request->input('user_id'),
            'user_subscription_plan_id' => $request->input('subscription_plan_id'),
            'name' => $userSubscription['name'],
            'description' => $userSubscription['description'],
            'duration' => $userSubscription['duration'],
            'start_datetime' => $start_date,
            'end_datetime' => $end_date,
            'amount' => $userSubscription['amount'],
            'invoice_id' => '',
            'transection_datetime' => '',
            'created_by' => '1',
            'status_id' => '1', )
        );
        dd(UserSubscription::insert($user_subscription_array));

UserSubscription내 모델 이름입니다. 삽입에 성공하면 "true"를 반환하고 그렇지 않으면 "false"를 반환합니다.


-1

이 문제를 해결하기위한 더 많은 라 라벨 방법은 컬렉션을 사용하여 타임 스탬프를 활용하는 모델과 함께 삽입하는 것입니다.

<?php

use App\Continent;
use Illuminate\Database\Seeder;

class InitialSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        collect([
            ['name' => 'América'],
            ['name' => 'África'],
            ['name' => 'Europa'],
            ['name' => 'Asia'],
            ['name' => 'Oceanía'],
        ])->each(function ($item, $key) {
            Continent::forceCreate($item);
        });
    }
}

편집하다:

오해해서 미안해 대량 삽입의 경우 도움이 될 수 있으며 아마도 이것으로 좋은 파종기를 만들고 조금 최적화 할 수 있습니다.

<?php

use App\Continent;
use Carbon\Carbon;
use Illuminate\Database\Seeder;

class InitialSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $timestamp = Carbon::now();
        $password = bcrypt('secret');

        $continents = [
            [
                'name' => 'América'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'África'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'Europa'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'Asia'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
            [
                'name' => 'Oceanía'
                'password' => $password,
                'created_at' => $timestamp,
                'updated_at' => $timestamp,
            ],
        ];

        Continent::insert($continents);
    }
}

1
이것은 항목 당 하나의 쿼리를 만듭니다. 대량 삽입이 아닙니다.
Emile Bergeron

1
@EmileBergeron 동의합니다. 내 게시물을 편집 했으므로 대량 삽입에 도움이 될 수 있습니다. 루프에서 많은 시간이 걸리는 작업 (탄소, 암호화)을 남겨두면 많은 시간을 절약 할 수 있습니다.
Francisco Daniel

-1

범주 관계 삽입의 경우 동일한 문제가 발생했으며 웅변 모델에서 Self ()를 사용하여 foreach에서 동일한 클래스의 인스턴스를 사용하여 여러 저장 및 잡기 ID를 기록한다는 점을 제외하고는 동일한 문제가 발생했습니다.

foreach($arCategories as $v)
{                
    if($v>0){
        $obj = new Self(); // this is to have new instance of own
        $obj->page_id = $page_id;
        $obj->category_id = $v;
        $obj->save();
    }
}

"$ obj = new Self ()"가 없으면 단일 레코드 만 저장합니다 ($ obj가 $ this 인 경우).


-4

문제 해결 ... 마이그레이션을위한 테이블 변경

$table->timestamp('created_at')->nullable()->useCurrent();

해결책:

Schema::create('spider_news', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('source')->nullable();
    $table->string('title')->nullable();
    $table->string('description')->nullable();
    $table->string('daterss')->nullable();

    $table->timestamp('created_at')->useCurrent();
    $table->timestamp('updated_at')->useCurrent();
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.