如何将mysql存储过程的结果转换为shell脚本中的JSON数据?

时间:2017-12-15 06:51:05

标签: mysql json bash shell stored-procedures

我想将MySQL存储过程的结果转换为JSON数据并插入到另一个表中。

尝试varchar数据类型时工作正常,但我需要JSON或数组类型的数据。

call="CALL status(input1,@data1,@data2,@data3.......)
select="select @data1, @data2, @data3.....;"

output=$(mysql --user=root --password=xxx db << eof 
$call
$select
eof)

mysql --user=root --password=xxx db << eof  
insert into sam values ('$output');
eof

这是输出结果,但我需要像JSON这样的输出。如何构造为JSON并将值传递给MySQL中的插入查询。

@data1  @data2  @data3  @data4  @data5  @data6  ..................
1213    1174    367 57  8   7398    39  .............

这是我的存储过程:

DELIMITER ;;

CREATE PROCEDURE status(
 IN input1 INT,
 IN input2 INT,
 OUT data1 INT,
 OUT data2 INT,
 OUT data3 INT)

BEGIN

--  data1
select count(*) INTO data1 from account where time >=input1 and time >=input2;

-- data2
SELECT SUM(if(status>0,1,0)) INTO data2 from account where time >=input1 and time >=input2;

-- data3
SELECT SUM(if(status=0,1,0)) INTO data3 from account where time >=input1 and time >=input2;

END

;;

如何构建像JSON这样的输出?我是这个话题的新手!!

1 个答案:

答案 0 :(得分:1)

MySQL 5.7.8或更高版本支持JSON data type

  

从MySQL 5.7.8开始,MySQL支持本机JSON数据类型

如果是这种情况,那么您可以重写存储过程以直接输出所需的JSON数据。

示例数据

SET @data1 = 1213;
SET @data2 = 1174;
SET @data3 = 367;
SET @data4 = 57;
SET @data5 = 8;
SET @data6 = 7398;

示例SELECT

SELECT JSON_MERGE(
    JSON_OBJECT('@data1', @data1),
    JSON_OBJECT('@data2', @data2),
    JSON_OBJECT('@data3', @data3),
    JSON_OBJECT('@data4', @data4),
    JSON_OBJECT('@data5', @data5),
    JSON_OBJECT('@data6', @data6)
);

输出 (为了更好的可读性而打印漂亮)

{
    "@data1": 1213,
    "@data2": 1174,
    "@data3": 367,
    "@data4": 57,
    "@data5": 8,
    "@data6": 7398
}

然后,为了获得MySQL JSON处理功能,目标列应该具有JSON数据类型。像这样你就可以在mysql中查询你的json。

<强>

如果您没有权限重写存储过程,则可以使用以下脏解决方案。只需将mysql的输出管道(|)输入awk(例如),我们为所需的字段应用必要的格式。为此目的而设计的工具会做得更好,例如:jojq

mysql --login-path=local -s -e 'SET @data1 = 1213; SET @data2 = 1174; SET @data3 = 367; SET @data4 = 57; SET @data5 = 8; SET @data6 = 7398; SELECT @data1, @data2, @data3, @data4, @data5, @data6' | awk '{ print "{\"@data1\":"$1",", "\"@data2\":"$2",", "\"@data3\":"$3",", "\"@data4\":"$4",", "\"@data5\":"$5",", "\"@data6\":"$6"}"}'

请注意我用于mysql身份验证的--login-path=local而不是-u ... -p...Read more here)。

更新 (仅适用于MySQL 5.7.8或更新版本)

我会改写你的存储过程:

DROP PROCEDURE IF EXISTS status_json;
DELIMITER @@
CREATE PROCEDURE status_json (
    IN input1 INT,
    IN input2 INT,
    OUT data JSON
)
proc: BEGIN

    SELECT JSON_MERGE(
       JSON_OBJECT('count', (SELECT COUNT(*) FROM account WHERE time >= input1 AND time >= input2)),
       JSON_OBJECT('sum_gt_0', (SELECT SUM(IF(status > 0, 1, 0)) FROM account WHERE time >= input1 AND time >= input2)),
       JSON_OBJECT('sum_eq_0', (SELECT SUM(IF(status = 0, 1, 0)) FROM account WHERE time >= input1 AND time >= input2))
    ) INTO data;

END proc @@
DELIMITER ;

称之为:

CALL status_json(123, 456, @json);

并使用ouptut:

SELECT @json;

重写存储过程的示例

<强>

CREATE TABLE account (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    time INT UNSIGNED NOT NULL,
    status TINYINT UNSIGNED NOT NULL
);

<强> 数据

INSERT INTO account (time, status) VALUES
(1513329548, 0),
(1513329528, 1),
(1513329508, 1),
(1513329648, 0),
(1513329148, 1),
(1513329540, 0),
(1513322548, 0),
(1513327548, 1);

CALL和SELECT

CALL status_json(1513329508, 1513322548, @json);
SELECT @json;

<强> 结果

{"count": 5, "sum_eq_0": 3, "sum_gt_0": 2}