Baspa
Baspa

Reputation: 1168

firstOrCreate returns Integrity constraint violation: 1062 Duplicate entry

I have a database seeder where I want to seed a Topic table. These are saved per Organization. The name of the Topic is a key. For each Organization there are multiple Topics, and sometimes an array with the same names could be inserted. To avoid this error:

Integrity constraint violation: 1062 Duplicate entry

I am using the firstOrCreate option from Eloquent. It looks for the organization_id and the name. If they don't exist together yet, it should insert a record, else it should skip inserting the record.

public function run($organizationId, $topicName)
    {
        $this->disableForeignKeys();

        $topic = Topic::allTenants()
            ->firstOrCreate([
                'organization_id' => $organizationId,
                'name' => $topicName,
            ], [
                'description' => 'Not used',
            ]);

        $this->enableForeignKeys();

        return $topic->id;
    }

But when I insert a Topic, with an unused organization_id it gives me the error that the record already exist. But that isn't the case because the organization_id and name don't exist in the database yet. So why does it give me this error? It looks like it isn't even checking for both organization_id and name.

These are the Schemas for the Topics table:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TopicsUniqueFields extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('topics', function (Blueprint $table) {
            $table->unique(['organisation_id', 'name']);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('topics', function (Blueprint $table) {
            $table->dropUnique(['organisation_id', 'name']);
        });
    }
}

The one above sets the unique fields for the Topics table.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

class CreateTopicsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('topics', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('organisation_id');
            $table->string('name');
            $table->text('description')->nullable();
            $table->timestamps();

            $table->foreign('organisation_id')
                ->references('id')->on('organisations');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('topics');
    }
}

Upvotes: 1

Views: 746

Answers (1)

rosscooper
rosscooper

Reputation: 2045

Is is definitely the organization_id or name fields that are duplicated, do you have any other unique fields on your table?

The only other think I could think of is Topic::allTenants() method limiting the scope of the query? i.e. Topics exist with the organization_id or name field that are out of scope of the query.

Upvotes: 1

Related Questions