如何使用 Laravel Eloquent 更新 PostgresQL 中 jsonb 列的多个“键”

Posted

技术标签:

【中文标题】如何使用 Laravel Eloquent 更新 PostgresQL 中 jsonb 列的多个“键”【英文标题】:How to update mulltiple "keys" of a jsonb column in PostgresSQL using Laravel Eloquent 【发布时间】:2021-09-09 13:52:09 【问题描述】:

尝试使用 Laravel Eloquent 更新 PostgresSQL 中 jsonb 列的多个“键”,并引发以下异常

SQLSTATE[42601]: Syntax error: 7 ERROR:  multiple assignments to same column "options" (SQL: update "specs" set "options" = jsonb_set("options"::jsonb, '"php"', "8.1.0"), "options" = jsonb_set("options"::jsonb, '"laravel"', "master"), "options" = jsonb_set("options"::jsonb, '"db"', "14"), where "id" = 1)

架构

Schema::create('specs', function (Blueprint $table) 
    $table->id();
    $table->jsonb('options')->nullable();
);

options 列的值将有多个键,例如:phplaraveldb

"php": "7.0.8", "laravel": "8.47.0", "db": "postgres 13.3"

我正在尝试更新以下值,有没有其他方法可以生成“正确”的 SQL 查询

$values = [
   "options->php" => "8.1.0",
   "options->laravel" => "master",
   "options->db" => "14",
];
Specs::where('id', 1)->update($values);

正确的 SQL 查询应该是以下任一

-- Recursive
update "specs"
set "options" = jsonb_set(
        jsonb_set(
            jsonb_set(
                "options" :: jsonb,
                '"db"',
                "14"
            ),
            '"laravel"',
            "master"
        ),
        '"php"',
        "8.1.0"
    ),
where "id" = 1;

-- Merge
update "specs"
set "options" = options || '"php": "8.1.0", "laravel": "master", "db": "14"',
where "id" = 1

【问题讨论】:

【参考方案1】:

要更新jsonb 列中的记录,您可以使用以下命令:

$values = [
   "options" => [
       "php" => "8.1.0",
       "laravel" => "master",
       "db" => "14",
    ]
];

Specs::where('id', 1)->update($values);

【讨论】:

这将从 db.json 中删除保存在 json 中的其他键。我只想更新几个键并保持其他键不变

以上是关于如何使用 Laravel Eloquent 更新 PostgresQL 中 jsonb 列的多个“键”的主要内容,如果未能解决你的问题,请参考以下文章

Laravel eloquent 使用关系列更新列

Laravel (Eloquent) 不更新数据库

使用 Laravel Eloquent 使用复合键更新表

Laravel 不使用 Eloquent 更新项目

如何使用 Laravel 的 Eloquent/Fluent 将每一行设置为相同的值?

更新 laravel 关系中的许多记录