2017-06-21 101 views
2

目标是返回JSON数据类型中缺少某个键的所有记录。这只是为了明显的,我想查询JSON结构的任何东西,其中faultyField返回以下表中的数据中nullpostgresql未定义的json字段不会按预期返回null

id::SERIAL |  data::JSON 
------------+------------------- 
      1 | {"key" : "val"} 
      2 | {"key1" : "val2"} 

任何以下两个语句:

SELECT * FROM test WHERE data->>'faultyField' = null; 
SELECT * FROM test WHERE (data->>'faultyField')::text = 'null'; 

应该返回所有的价值(根据我在工作中发现的两个SO帖子)?但它不是因为某种原因。这两个只是返回空结果。

我不是使用PostgreSQL的向导,所以我尝试了下面这些语句之间的所有内容,只是为了看看它们是否可以工作。可悲的是,他们没有。

SELECT * FROM test WHERE (SELECT json_object_keys(data) FROM test)='key'; 
SELECT * FROM test WHERE 'key' in json_object_keys(data); 
SELECT * FROM test WHERE 'key' := json_object_keys(data); 
SELECT * FROM test WHERE 'key' ANY (json_object_keys(data)); 

有没有办法返回JSON字符串中缺少密钥的记录?

回答

3

请勿使用=null。尝试:

select * 
from test 
where data->>'faultyField' is null; 

the documentation

不要写表达式= NULL因为NULL是不 “等于” NULL。 (NULL代表一个未知的值,它不知道两个未知的数值是否相等。)

+0

我想操作系统试图检查一个密钥是否存在,而不是测试它的值。在这种情况下,'data - >>'faultyField'为null'将返回行,即使'faultyField'键存在并且具有空值。但我可能是错的。 –

+0

呃,你错了。 'data - >>'faultyField'为null'当且仅当密钥丢失时才为真。 – klin

+0

你确定吗? 'CREATE TEMP TABLE test AS SELECT 1 AS id,'{“key”:null}':: JSONB AS data; SELECT * FROM test WHERE data - >>'key'IS NULL;'。这个测试用例按我的预期返回该行。测试9.5.6。 –

4

编辑

我严重推荐您使用JSONB,而不是JSON。它是一个更强大的类型,它允许索引和其他运算符,如下面所示。


如果你想测试一个关键不在工作jsonb现场使用的顶级存在 ?操作:

CREATE TEMP TABLE test AS VALUES 
    (1, '{"key" : "val"}'::JSONB), 
    (2, '{"key2" : "val2"}'::JSONB); 

SELECT * FROM test WHERE NOT column2 ? 'key3'; 

使用data->>'faultyField'将尝试获得此键的值,而不是测试,如果键存在。这不是您要查找的内容,因为它将返回行,即使faultyField键存在且具有空值。

+0

'没有操作符匹配给定的名称和参数类型。你可能需要在'?'上添加明确的类型转换 - 为什么? – Torxed

+0

自9.4开始,'?'运算符就存在于'JSONB'类型中。什么是您的PostgreSQL版本?有关[docs]的更多信息(https://www.postgresql.org/docs/current/static/functions-json.html)。 –

+0

我现在在摇摆v9.6.1。 JSONB用于字节数据tho? – Torxed