'cannot extract element from a scalar' 当 order by id 为 DESC

'cannot extract element from a scalar' when order by id is DESC

我有一个 PostgreSQL 9.3.10 数据库,一个包含 15842 条记录的 table 并使用 Intellij 进行查询。 我想从 JSON 列(名为 'data')查询一些最近的数据。

我的查询就这么简单:

select data->'header'
from some_table
order by id desc

问题是我得到:

[22023] ERROR: cannot extract element from a scalar

当我使用desc命令时。当我使用 asc 时,查询不会失败并且至少会收到前 500 条记录。

对我来说,最近的一些记录似乎无效 JSON。如果是这样,我怎样才能忽略坏记录并仍然使用 DESC 排序执行查询?或者如何识别损坏的 JSON 记录?

我也认为它可能是由空数据引起的,但是select * from table where data is null没有显示任何结果。

UPD:'data' 列的类型是 json。我发现有些行将 json 数据序列化为字符串(因为后端有问题)。所以不是正常的 json object: {} 值是一个引用对象 string "{}"。通过以下查询检测到:select data from some_table where data::text not like '{%'

您对问题的描述表明 data 列不是使用正确的数据类型创建的。如果是 jsonjsonb,则错误数据将在插入时被拒绝。

我认为 Postgres 没有内置函数来检查 JSON 字符串的有效性。您需要创建一个,例如:

create or replace function is_jsonb(js text)
    returns boolean
as $$
begin
    return (js::jsonb is not null);
exception 
    when others then return false;  
end;
$$
language plpgsql;

然后您可以在查询中使用它:

select *
from mytable
where not is_jsonb(data);

根据 data 的数据类型,可能需要额外的转换,例如:

where not is_jsonb(data::text);

问题是由 ActiveRecord 版本更新引起的,它导致接收 to_json 的 Ruby 对象显式写为单个字符串,这也是一个有效的 JSON 数据(Postgres 调用它:错误消息中的“标量”)。 这就是为什么仅在使用 by id desc 的查询中出现错误(仅适用于 ActiveRecord 更新后创建的新记录)。这是关于 ActiveRecord 更改的注释:https://github.com/rails/rails/commit/835246e622dc0431af3cb951db22ef78876006af

所以写成 "{\"header\": \"value\"}" 而不是 {"header": "value"}。 数据库已通过以下查询修复:

update some_table 
set data = REPLACE(TRIM(BOTH '"' from data::text), '\"', '"')::JSON 
where data::text like '"%';