'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
列不是使用正确的数据类型创建的。如果是 json
或 jsonb
,则错误数据将在插入时被拒绝。
我认为 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 '"%';
我有一个 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
列不是使用正确的数据类型创建的。如果是 json
或 jsonb
,则错误数据将在插入时被拒绝。
我认为 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 '"%';