web-dev-qa-db-fra.com

Comment interroger une colonne JSON pour des objets vides?

Vous cherchez toutes les lignes où une certaine colonne JSON contient un objet vide, {}. Cela est possible avec les tableaux JSON ou si je recherche une clé spécifique dans l'objet. Mais je veux juste savoir si l'objet est vide. Je n'arrive pas à trouver un opérateur capable de le faire.

 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

Il n'y a pas d'opérateur d'égalité (ou d'inégalité) pour le type de données json dans son ensemble, car l’égalité est difficile à établir. Considérez jsonb dans Postgres 9.4 ou version ultérieure, lorsque cela est possible. Plus de détails dans cette réponse relative à dba.SE (dernier chapitre):

SELECT DISTINCT json_column ... ou ... GROUP BY json_column échouer pour la même raison (pas d'opérateur d'égalité).

La conversion des deux côtés de l'expression en text permet à = ou <> opérateurs, mais ce n’est pas normalement fiable car il existe de nombreuses représentations textuelles possibles pour la valeur mêmejson.

Cependant, pour ce cas particulier ( objet vide ) cela fonctionne très bien :

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

A partir de PostgreSQL 9.5, ce type de requête avec des données JSON est impossible. D'autre part, je suis d'accord que ce serait très utile et créé une demande pour cela:

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

N'hésitez pas à voter, et j'espère que cela sera mis en œuvre!

5
Pensierinmusica

En 9.3, il est possible de compter les paires dans chaque objet et de filtrer celles qui n'en ont aucune.

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

ou tester l'existence, probablement plus rapide pour les gros objets

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

Les deux techniques fonctionneront parfaitement, quel que soit le formatage

2
Clodoaldo Neto

Tableau JSON vide [] pourrait également être pertinent.

Ensuite, cela pourrait fonctionner pour les deux [] et {}:

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