J'ai les tables suivantes et leur relation. Je stocke des données JSON dans la table client_services. Est-ce un moyen de récupérer les valeurs JSON en utilisant la requête mysql. comme:
select getJson("quota") as quota, client_id from client_services where service_id =1;
OU
Puis-je normaliser davantage la table client_services?
Prestations de service:
+----+-----------------------+--------------------------------------------------------+
| id | name | description |
+----+-----------------------+--------------------------------------------------------+
| 1 | MailBox | |
| 2 | SMS | |
| 3 | FTP | |
+----+-----------------------+--------------------------------------------------------+
service_features:
+----+------------+----------------------------------+------------------------+
| id | service_id | name | description |
+----+------------+----------------------------------+------------------------+
| 10 | 1 | Forwarding | Forward Mail |
| 11 | 1 | Archive | Archive Mail |
| 12 | 1 | WebMail | NULL |
| 13 | 1 | IMAP | NULL |
| 14 | 2 | Web SMS | NULL |
+----+------------+----------------------------------+------------------------+
services clients:
+-----+-----------+------------+-------------------------------------------------------------------------------------------+
| id | client_id | service_id | service_values |
+-----+-----------+------------+-------------------------------------------------------------------------------------------+
| 100 | 1000 | 1 |{ "quota": 100000,"free_quota":20000,"total_accounts":200,"data_transfer":1000000} |
| 101 | 1000 | 2 |{ "quota": 200 } |
| 102 | 1000 | 3 |{ "data_transfer":1000000} |
| 103 | 1001 | 1 |{ "quota": 1000000,"free_quota":2000,"total_accounts":200,"data_transfer":1000000} |
| 104 | 1001 | 2 |{ "quota": 500 } |
| 105 | 1002 | 2 |{ "quota": 600 } |
+-----+-----------+------------+-------------------------------------------------------------------------------------------+
client_feature_mappers:
+-----+-------------------+--------------------+-----------+
| id | client_service_id | service_feature_id | client_id |
+-----+-------------------+--------------------+-----------+
|10000| 100| 10 | 1000|
|10001| 100| 11 | 1000|
|10002| 100| 12 | 1000|
|10003| 100| 13 | 1000|
|10004| 101| 14 | 1000|
|10005| 103| 10 | 1001|
|10006| 101| 11 | 1001|
|10007| 101| 12 | 1001|
|10008| 101| 13 | 1001|
|10009| 105| 14 | 1002|
+-----+-------------------+--------------------+-----------+
Étant donné que beaucoup de gens m'ont posé cette question personnellement, j'ai pensé que je donnerais à cette réponse une deuxième révision. Voici un Gist qui contient le code SQL complet avec SELECT, la migration et la création de vues et un violon sql en direct(disponibilité non garantie pour le violon).
Disons que vous avez une table (nommée: JSON_TABLE) comme ceci:
ID CITY POPULATION_JSON_DATA
-----------------------------------------------------------------------
1 LONDON {"male" : 2000, "female" : 3000, "other" : 600}
2 NEW YORK {"male" : 4000, "female" : 5000, "other" : 500}
Pour sélectionner chaque champs JSON, vous pouvez faire:
SELECT
ID, CITY,
json_extract(POPULATION_JSON_DATA, '$.male') AS POPL_MALE,
json_extract(POPULATION_JSON_DATA, '$.female') AS POPL_FEMALE,
json_extract(POPULATION_JSON_DATA, '$.other') AS POPL_OTHER
FROM JSON_TABLE;
qui résulte:
ID CITY POPL_MALE POPL_FEMALE POPL_OTHER
-----------------------------------------------------------------
1 LONDON 2000 3000 600
2 NEW YORK 4000 5000 500
Cela peut être une opération coûteuse à exécuter en fonction de la taille de vos données et de la complexité de votre JSON. Je suggère de l'utiliser pour
Faites attention à: Vous pouvez avoir json commençant par des guillemets doubles (stringifié):
"{"male" : 2000, "female" : 3000, "other" : 600}"
Testé avec Mysql 5.7 sur Ubuntu et Mac OSX Sierra.
Vous pouvez utiliser la fonction MySQL SUBSTRING_INDEX pour décomposer la chaîne JSON:
SELECT
SUBSTRING_INDEX(
SUBSTRING_INDEX(
SUBSTRING_INDEX( service_values, 'quota', -1),
'": ', -1),
' ', 1) AS quota,
client_id
FROM client_services
WHERE service_id=1;
Tout d'abord, vous devez savoir que votre modèle ci-dessus n'est pas sous la première forme normale, ce qui signifie que vous ne devez avoir qu'une seule valeur dans chaque champ. Cependant, cette définition dépend des besoins de traitement de votre requête d'application.
Donc, si tout ce que vous voulez, c'est mettre un tas de données JSON dans un champ et le renvoyer à l'application tel quel, alors tout va bien. Vous pouvez renvoyer l'intégralité des données JSON et laisser l'application sélectionner les attributs JSON de son choix.
Mais si vous avez des requêtes, comme dans votre cas, ayant des critères ou des expressions de champ pour examiner les détails des données JSON, alors c'est définitivement impossible. Ce sera un cauchemar en termes de complexité des requêtes et de lenteur du traitement.
Vous pouvez bien entendu normaliser davantage vos tables pour remplacer complètement la structure de données JSON. Toutefois, si votre application nécessite un schéma flexible, peut-être la principale raison d'utiliser les bases de données NOSQL, mais que vous êtes coincé avec MySQL, il existe deux solutions:
a) utilisez MySQL 5.6 (ou MariaDB v. ??) pour le support NoSQL (je n’ai pas examiné les détails) http://www.computerworld.com/s/article/9236511/MySQL_5.6_tackles_NoSQL_competitors .__ Les colonnes dynamiques de .MariaDB: https://kb.askmonty.org/en/dynamic-columns/
b) utiliser mysql sans schéma explicite, voir ici pour une solution très bien faite, qui ne pose aucun problème d’évolutivité: http://backchannel.org/blog/friendfeed-schemaless-mysql
SET @a = '[{"x": 2, "y": "8"}, {"x": "3", "y": "7"}, {"x": "4", " y ": 6}] ';
SELECT * FROM JSON_TABLE ( @ A, "$ [*]" COLONNE ( Xval VARCHAR (100) PATH "$ .x", Yval VARCHAR (100 ) CHEMIN "$ .y" )) AS jt1;