web-dev-qa-db-de.com

Wie fragt man eine JSON-Spalte nach leeren Objekten ab?

Auf der Suche nach allen Zeilen, in denen eine bestimmte json-Spalte ein leeres Objekt enthält, {}. Dies ist mit JSON-Arrays möglich oder wenn ich nach einem bestimmten Schlüssel im Objekt suche. Aber ich möchte nur wissen, ob das Objekt leer ist. Ich kann anscheinend keinen Operator finden, der dies tut.

 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.
51
sbeam

Es gibt keinen Gleichheits oder Ungleichheits-) Operator für den Datentyp json als Ganzes, weil es schwierig ist, Gleichheit herzustellen. Berücksichtigen Sie --- (jsonb in Postgres 9.4 oder höher, wo dies möglich ist. Weitere Details in dieser verwandten Antwort auf dba.SE (letztes Kapitel):

SELECT DISTINCT json_column ... oder ... GROUP BY json_column aus dem gleichen Grund fehlschlagen (kein Gleichheitsoperator).

Wenn Sie beide Seiten des Ausdrucks in text umwandeln, wird = oder <> -Operatoren, aber das ist normalerweise nicht zuverlässig, da es viele mögliche Textdarstellungen für den Wert samejson gibt.

Für diesen speziellen Fall ( leeres Objekt ) funktioniert es jedoch einwandfrei :

select * from test where foo::text <> '{}'::text;
96

Ab PostgreSQL 9.5 ist diese Art der Abfrage mit JSON-Daten nicht möglich. Andererseits bin ich damit einverstanden, dass es sehr nützlich wäre, und habe eine Anfrage dafür erstellt:

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

Fühlen Sie sich frei, um es abzustimmen, und hoffentlich wird es umgesetzt!

5
Pensierinmusica

In 9.3 ist es möglich, die Paare in jedem Objekt zu zählen und diejenigen mit keiner zu filtern

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 
-----
 {}

oder testen Sie die Existenz, wahrscheinlich schneller für große Objekte

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

Beide Techniken funktionieren unabhängig von der Formatierung einwandfrei

2
Clodoaldo Neto

Leeres JSON-Array [] könnte auch relevant sein.

Dann könnte dies für beide funktionieren [] und {}:

select * from test where length(foo::text) > 2 ;
1
weinerk