Laravel Eloquent的upsert方法不识别UUID主键并生成插入语句。

huangapple go评论75阅读模式
英文:

Laravel Eloquent upsert method does not recognise UUID primary key and generates insert statement

问题

我正在处理以下代码项目:

模式

Schema::create('form_pages', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->foreignUuid('form_id')
        ->index()
        ->constrained()
        ->onDelete('cascade');
    $table->string('name');
    $table->integer('sort');
    $table->timestamps();
});

模型

class FormPage extends Model
{
    use HasFactory;
    use HasUuids;
    
    /**
     * {@inheritDoc}
     */
    protected $fillable = [
        'id',
        'form_id',
        'name',
        'sort',
    ];

    // ...
}

Eloquent upsert

FormPage::upsert(
    [
        [
            "id" => "23456693-9011-3c27-9556-408044349520",
            "sort" => 0,
        ],
        [
            "id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
            "sort" => 2,
        ],
        [
            "id" => "b1964720-e475-3733-898b-d4084863dd24",
            "sort" => 1,
        ],
    ],
    ['id'],
    ['sort'],
);

记录已存在于数据库中,唯一变化的是sort列的值,但是Eloquent似乎无法识别它们并抛出以下错误:

Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: form_pages.name (Connection: sqlite, SQL: insert into "form_pages" ("created_at", "form_id", "id", "sort", "updated_at") values (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 83e4ff46-eb0a-3587-ba75-832635c242b4, 0, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 30c09d4d-7418-31d7-ac1e-5371bcf12f67, 2, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 26eaa72b-ac62-3c54-aee9-7c0faf7392ce, 1, 2023-05-24 17:11:35) on conflict ("id") do update set "sort" = "excluded"."sort", "updated_at" = "excluded"."updated_at")

根据Laravel的文档

除了SQL Server之外的所有数据库都要求upsert方法的第二个参数中的列具有“primary”或“unique”索引。此外,MySQL数据库驱动程序会忽略upsert方法的第二个参数,并始终使用表的“primary”和“unique”索引来检测现有记录。

我在MySQL 8上运行此操作,但可能有些遗漏 - 非常感谢您的帮助。

英文:

I'm working on the project with the following code:

Schema

Schema::create('form_pages', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->foreignUuid('form_id')
        ->index()
        ->constrained()
        ->onDelete('cascade');
    $table->string('name');
    $table->integer('sort');
    $table->timestamps();
});

Model

class FormPage extends Model
{
    use HasFactory;
    use HasUuids;
    
    /**
     * {@inheritDoc}
     */
    protected $fillable = [
        'id',
        'form_id',
        'name',
        'sort',
    ];

    // ...
}

Eloquent upsert

FormPage::upsert(
    [
        [
            "id" => "23456693-9011-3c27-9556-408044349520",
            "sort" => 0,
        ],
        [
            "id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
            "sort" => 2,
        ],
        [
            "id" => "b1964720-e475-3733-898b-d4084863dd24",
            "sort" => 1,
        ],
    ],
    ['id'],
    ['sort'],
);

The records already exist in the database and the only thing that changes is the value of the sort column, but eloquent doesn't seem to recognise them and throws the following error

> Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: form_pages.name (Connection: sqlite, SQL: insert into "form_pages" ("created_at", "form_id", "id", "sort", "updated_at") values (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 83e4ff46-eb0a-3587-ba75-832635c242b4, 0, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 30c09d4d-7418-31d7-ac1e-5371bcf12f67, 2, 2023-05-24 17:11:35), (2023-05-24 17:11:35, b1681611-ea6b-3e91-afc1-f45458a95552, 26eaa72b-ac62-3c54-aee9-7c0faf7392ce, 1, 2023-05-24 17:11:35) on conflict ("id") do update set "sort" = "excluded"."sort", "updated_at" = "excluded"."updated_at")

According to Laravel's documentation:

> All databases except SQL Server require the columns in the second argument of the upsert method to have a "primary" or "unique" index. In addition, the MySQL database driver ignores the second argument of the upsert method and always uses the "primary" and "unique" indexes of the table to detect existing records.

I'm running this on MySQL 8, but perhaps there is something I missed - any help would be much appreciated.

答案1

得分: 0

It seems that I've forgotten that during the INSERT INTO ... ON DUPLICATE KEY UPDATE statement, if you have any of the columns set as NOT NULL, you have to provide the value for them in the first argument. After refactoring my code and adding the mandatory name index, the upsert statement now looks like this:

FormPage::upsert(
    [
        [
            "id" => "23456693-9011-3c27-9556-408044349520",
            'name' => 'Page 1',
            "sort" => 0,
        ],
        [
            "id" => "66accb28-aff2-3f4c-9006-7de7a6512e30",
            'name' => 'Page 2',
            "sort" => 2,
        ],
        [
            "id" => "b1964720-e475-3733-898b-d4084863dd24",
            'name' => 'Page 3',
            "sort" => 1,
        ],
    ],
    'id',
    ['sort'],
);
英文:

So it appears I've forgotten that during the INSERT INTO ... ON DUPLICATE KEY UPDATE statement, if you have any of the columns set as NOT NULL - you have to provide the value for them in the first argument (yep, error message says it loud enough). After refactoring my code and adding the mandatory name index the upsert statement now looks as follow

<!-- language: php -->

FormPage::upsert(
    [
        [
            &quot;id&quot; =&gt; &quot;23456693-9011-3c27-9556-408044349520&quot;,
            &#39;name&#39; =&gt; &#39;Page 1&#39;,
            &quot;sort&quot; =&gt; 0,
        ],
        [
            &quot;id&quot; =&gt; &quot;66accb28-aff2-3f4c-9006-7de7a6512e30&quot;,
            &#39;name&#39; =&gt; &#39;Page 2&#39;,
            &quot;sort&quot; =&gt; 2,
        ],
        [
            &quot;id&quot; =&gt; &quot;b1964720-e475-3733-898b-d4084863dd24&quot;,
            &#39;name&#39; =&gt; &#39;Page 3&#39;,
            &quot;sort&quot; =&gt; 1,
        ],
    ],
    &#39;id&#39;,
    [&#39;sort&#39;],
);

huangapple
  • 本文由 发表于 2023年5月25日 01:17:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76325982.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定