78

查找某个 json 列包含空对象的所有行,{}. 这对于 JSON 数组是可能的,或者如果我正在寻找对象中的特定键。但我只想知道对象是否为空。似乎找不到可以执行此操作的操作员。

 dev=# \d test
     Table "public.test"
  Column | Type | Modifiers
 --------+------+-----------
  foo    | json |

 dev=# select * from test;
    foo
 ---------
  {"a":1}
  {"b":1}
  {}
 (3 rows)

 dev=# select * from test where foo != '{}';
 ERROR:  operator does not exist: json <> unknown
 LINE 1: select * from test where foo != '{}';
                                      ^
 HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
 dev=# select * from test where foo != to_json('{}'::text);
 ERROR:  operator does not exist: json <> json
 LINE 1: select * from test where foo != to_json('{}'::text);
                                      ^
 HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
 dwv=# select * from test where foo != '{}'::json;
 ERROR:  operator does not exist: json <> json
 LINE 1: select * from test where foo != '{}'::json;
                                      ^
 HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
4

6 回答 6

142

整个数据类型没有相等(或不相等)运算符json,因为相等很难建立。考虑jsonb在 Postgres 9.4 或更高版本中,这是可能的。有关 dba.SE 的相关答案中的更多详细信息(最后一章):

SELECT DISTINCT json_column ...... GROUP BY json_column因相同原因失败(没有相等运算符)。

将表达式的两边都转换为text允许=<>运算符,但这通常不可靠,因为相同的JSON 值有许多可能的文本表示。在 Postgres 9.4 或更高版本中,jsonb改为转换为。(或用于jsonb开头。)

但是,对于这种特殊情况空对象),它工作得很好:

select * from test where foo::text <> '{}'::text;
于 2014-06-18T22:32:12.713 回答
11

空 JSON 数组[]也可能是相关的。

那么这可以同时适用于[]{}

select * from test where length(foo::text) > 2 ;
于 2019-05-30T17:13:40.103 回答
6

从 PostgreSQL 9.5 开始,这种类型的 JSON 数据查询是不可能的。另一方面,我同意它会非常有用并为此创建了一个请求:

https://postgresql.uservoice.com/forums/21853-general/suggestions/12305481-check-if-json-is-empty

随意投票,希望它会得到实施!

于 2016-02-12T16:41:04.773 回答
5

你必须要小心。将所有数据转换为不同的类型以便您可以比较它在大型数据库上会出现性能问题。

如果您的数据具有一致的密钥,那么您可以查找密钥的存在。例如,如果计划数据是 {} 或 {id: '1'}

然后您可以查找没有“id”的项目

SELECT * FROM public."user"
where NOT(plan ? 'id')
于 2020-05-08T21:25:10.627 回答
3

在 9.3 中,可以计算每个对象中的对并过滤没有的对

create table test (foo json);
insert into test (foo) values
('{"a":1, "c":2}'), ('{"b":1}'), ('{}');

select *
from test
where (select count(*) from json_each(foo) s) = 0;
 foo 
-----
 {}

或测试存在,对于大物体可能更快

select *
from test
where not exists (select 1 from json_each(foo) s);

无论格式化如何,这两种技术都可以完美地工作

于 2014-07-25T21:15:19.063 回答
1

According to the JSON Functions and Operators documentation you can use the double arrow function (->>) to get a json object or array field as text. Then do an equality check against a string.

So this worked for me:

SELECT jsonb_col from my_table
WHERE jsonb_col ->> 'key' = '{}';

Or if it's nested more than one level use the path function (#>>)

SELECT jsonb_col from my_table
WHERE jsonb_col #>> '{key, nestedKey}' = '{}';

Currently supported version as of this writing:

Supported Versions: Current (13) / 12 / 11 / 10 / 9.6

于 2021-04-15T16:14:24.930 回答