How to JSON extract from dynamic key value pair in MySQL?

前端 未结 4 2083
暖寄归人
暖寄归人 2021-01-25 22:40

I have the user table with user_id and user_details. it contains the JSON data in string format as shown below:

[{\"name\":\"question-1\",\"value\":\"sachin\",\"         


        
相关标签:
4条回答
  • 2021-01-25 23:02

    You don't use JSON_EXTRACT(). You use JSON_TABLE():

    mysql> create table mytable ( id serial primary key, data json);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> insert into mytable set data = '[{"name":"question-1","value":"sachin","label":"Enter your name?"},
        '>     {"name":"question-2","value":"abc@example.com","label":"Enter your email?"},
        '>     {"name":"question-3","value":"xyz","label":"Enter your city?"}]';
    Query OK, 1 row affected (0.00 sec)
    
    mysql> SELECT j.* FROM mytable,
      JSON_TABLE(data, '$[*]' COLUMNS (
        name VARCHAR(20) PATH '$.name', 
        label VARCHAR(50) PATH '$.label'
      )) AS j;
    +------------+-------------------+
    | name       | label             |
    +------------+-------------------+
    | question-1 | Enter your name?  |
    | question-2 | Enter your email? |
    | question-3 | Enter your city?  |
    +------------+-------------------+
    

    JSON_TABLE() requires MySQL 8.0.4 or later. If you aren't running at least that version, you will have to upgrade.

    Honestly, if you need to access the individual fields, it's less work to store your data in normal columns, and avoid using JSON.

    0 讨论(0)
  • 2021-01-25 23:04

    I assume that you are not using a table.

    SET @data = '[{"name":"question-1","value":"sachin","label":"Enter your name?"},
        {"name":"question-2","value":"abc@example.com","label":"Enter your email?"},
        {"name":"question-3","value":"xyz","label":"Enter your city?"}]';
    
    SELECT JSON_EXTRACT(@data,'$[*].name') AS "name", JSON_EXTRACT(@data,'$[*].label') AS "label";
    

    it will return

    name                                           |  label
    ["question-1", "question-2", "question-3"]     |  ["Enter your name?", "Enter your email?", "Enter your city?"]
    

    SQL should be like below according to your table and column name:

    SELECT JSON_EXTRACT(user_details,'$[*].name') AS "name", JSON_EXTRACT(user_details,'$[*].label') AS "label" FROM user;
    

    you can match them by using some loops for arrays. I do not know if this is the best way but it satisfy my needs.

    0 讨论(0)
  • 2021-01-25 23:08

    Another answer given by How to extract rows from a json array using the mysql udf json_extract 0.4.0? is to parse yourself the JSON with common_schema. Pretty tricky if you are not used to complex SQL.

    You could create an own aggregated table as proposed in topic List all array elements of a MySQL JSON field if you know how many elements will be given by the field but I guess this is not your case.

    However, it seems better, as mentioned in both answers, not to store such json lists in your SQL database. Maybe could you make a related table containing one line per each dictionary and then link it to your main table with a foreign key.

    0 讨论(0)
  • 2021-01-25 23:11

    I was working in a report where there was a big json array list in one column. I modified the datamodel to store the relationship 1 to * instead of storing everything in one single column. For doing this process, I had to use a while in a stored procedure since I do not know the maximum size:

    DROP PROCEDURE IF EXISTS `test`;
    
    DELIMITER #
    
    CREATE PROCEDURE `test`()
    PROC_MAIN:BEGIN
    DECLARE numNotes int;
    DECLARE c int;
    DECLARE pos varchar(10);
    
    SET c = 0;
    SET numNotes = (SELECT 
    ROUND (   
            (
                LENGTH(debtor_master_notes)
                - LENGTH( REPLACE ( debtor_master_notes, "Id", "") ) 
            ) / LENGTH("Id")        
        ) AS countt FROM debtor_master
    order by countt desc Limit 1);
    
    DROP TEMPORARY TABLE IF EXISTS debtorTable;
    CREATE TEMPORARY TABLE debtorTable(debtor_master_id int(11), json longtext, note int);
    WHILE(c <numNotes) DO
    SET pos = CONCAT('$[', c, ']');
    INSERT INTO debtorTable(debtor_master_id, json, note)
    SELECT debtor_master_id, JSON_EXTRACT(debtor_master_notes, pos), c+1
    FROM debtor_master
    WHERE debtor_master_notes IS NOT NULL AND debtor_master_notes like '%[%' AND JSON_EXTRACT(debtor_master_notes, pos) IS NOT NULL AND JSON_EXTRACT(debtor_master_notes, pos) IS NOT NULL;
    SET c = c + 1;
    END WHILE;
    SELECT * FROM debtorTable;
    END proc_main #
    
    DELIMITER ;
    
    0 讨论(0)
提交回复
热议问题