MariaDb vs MySQL JSON_ARRAYAGG JSON_OBJECT 没有转义
MariaDb vs MySQL JSON_ARRAYAGG JSON_OBJECT Without Escaping
我有一个 select 查询,它在我的本地主机 MySQL 数据库环境中工作得很好。它应该 return json object.
当我在安装了 MariaDB 10.5.15 的托管 public 服务器上 运行 相同的查询时,returned json 包含几个反斜杠、转义字符。
代码如下:
SELECT
json_object(
'id', C1.Category1ID,
'text', C1.Category1Name,
'nodes', JSON_ARRAYAGG(
JSON_OBJECT(
'id', C2.Category2ID,
'text', C2.Category2Name,
'nodes', C2.nodes,
'class', 'nav-level-2',
'href', 'admin-categories-2.php'
)
),
'class', 'nav-level-1',
'href', 'admin-categories-1.php'
) AS JSON
FROM categories_1 C1
LEFT JOIN (
SELECT
C2.Category1ID,
C2.Category2ID,
C2.Category2Name,
JSON_ARRAYAGG(
JSON_OBJECT(
'id', C3.Category3ID,
'text', C3.Category3Name,
'class', 'nav-level-3',
'href', 'admin-categories-3.php'
)
) as nodes
FROM categories_2 C2
LEFT JOIN categories_3 C3 ON C3.Category2ID = C2.Category2ID AND C3.Category3Status = 1
WHERE C2.Category2Status = 1
GROUP BY C2.Category2ID
ORDER BY C2.Category2Order, C3.Category3Order
) C2 ON C2.Category1ID = C1.Category1ID
WHERE C1.Category1Status = 1
GROUP BY C1.Category1ID
ORDER BY C1.Category1Order
;
我的问题是如何为 MariaDB 正确编写此查询。
我附上 MySQL (img1) 和 MariaDB (img2) 的结果。
我在此处附加了数据库的创建和插入语句:
CREATE TABLE `categories_1` (
`Category1ID` int(11) NOT NULL AUTO_INCREMENT,
`Category1Name` varchar(45) DEFAULT NULL,
`Category1Name_FR` varchar(45) DEFAULT NULL,
`Category1Photo` varchar(45) DEFAULT NULL,
`Category1Order` int(3) DEFAULT NULL,
`Category1Status` int(1) DEFAULT 1,
PRIMARY KEY (`Category1ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='Top level category'
CREATE TABLE `categories_2` (
`Category2ID` int(11) NOT NULL AUTO_INCREMENT,
`Category2Name` varchar(45) DEFAULT NULL,
`Category2Name_FR` varchar(45) DEFAULT NULL,
`Category2Order` int(3) DEFAULT NULL,
`Category2Status` int(1) DEFAULT 1,
`Category1ID` int(11) DEFAULT NULL COMMENT 'To which parent level category it fits',
PRIMARY KEY (`Category2ID`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='Mid level category'
CREATE TABLE `categories_3` (
`Category3ID` int(11) NOT NULL AUTO_INCREMENT,
`Category3Name` varchar(45) DEFAULT NULL,
`Category3Name_FR` varchar(45) DEFAULT NULL,
`Category3Order` int(3) DEFAULT NULL,
`Category3Status` int(1) DEFAULT 1,
`Category2ID` int(11) DEFAULT NULL COMMENT 'To which parent level category it fits',
PRIMARY KEY (`Category3ID`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COMMENT='Bottom level category'
INSERT INTO `categories_1` VALUES (1,'Meat','Meat-fr','meat.jpg',1,1),(2,'Fish & Sea Food',NULL,'fish.jpg',2,1),(3,'Fruit & Vegetables',NULL,'fruit-veg.jpg',3,1),(4,'Test L1',NULL,'categories-default.jpg',4,0);
INSERT INTO `categories_2` VALUES (1,'Beef','Feef-fr',1,1,1),(2,'Lamb',NULL,2,1,1),(3,'Pork',NULL,3,1,1),(4,'Veal',NULL,4,1,1),(5,'Poultry-Fowl',NULL,6,1,1),(6,'Sausages and Bacon',NULL,5,1,1),(7,'Salmon',NULL,8,1,2),(8,'Flat Fish',NULL,9,1,2),(9,'Common Fish',NULL,10,1,2),(10,'Squid family',NULL,11,1,2),(11,'Shellfish',NULL,12,1,2),(12,'Tuna',NULL,13,1,2),(13,'Other Fish',NULL,14,1,2),(14,'TEST L2',NULL,7,0,1);
INSERT INTO `categories_3` VALUES (1,'Specialist Beef','Specialist Beef-fr',1,1,1),(2,'Wagyu',NULL,2,1,1),(3,'Japanese Wagyu',NULL,3,1,1),(4,'Other Beef',NULL,4,1,1),(5,'All Lamb',NULL,6,1,2),(6,'All Pork',NULL,5,1,3),(7,'All Veal',NULL,7,1,4),(8,'All Poultry-Fowl',NULL,11,1,5),(9,'Pork Sausages',NULL,8,1,6),(10,'Other meats',NULL,9,1,6),(11,'Bacon',NULL,10,1,6),(12,'All Salmon',NULL,12,1,7),(13,'All Flat Fish',NULL,13,1,8),(14,'All Common Fish',NULL,14,1,9),(15,'All Squid family',NULL,15,1,10),(16,'All Shellfish',NULL,16,1,11),(17,'All Tuna',NULL,17,1,12),(18,'All Other Fish',NULL,18,1,13),(19,'TEST L3',NULL,999,0,14);
MariaDB 没有 JSON 数据类型(JSON 关键字只是 LONGTEXT 关键字的别名),它可能只将字符串类型值视为 JSON。
您使用构造JSON_ARRAYAGG( JSON_OBJECT( ...
。在 MariaDB 中,JSON_OBJECT 产生的值是字符串!它是 一个实心字符串 ,而不是 JSON 数据类型的复杂值。因此,在 JSON_ARRAYAGG 期间,处理包含引用所需字符的实心字符串值,并引用所有双引号字符。
参见 FIDDLE,尤其是最后一个和 pre-last 代码块。在 pre-last 块中,特别注意包裹整个值的双引号字符(不是由斜杠引用的内部双引号)。
我没有看到在 MariaDB 中解决这个问题的方法。没有方法告诉函数作为参数提供的值不是字符串而是 JSON - 没有这样的数据类型。
等到 MariaDB 实现 JSON 数据类型 (if) 并升级。
我有一个 select 查询,它在我的本地主机 MySQL 数据库环境中工作得很好。它应该 return json object.
当我在安装了 MariaDB 10.5.15 的托管 public 服务器上 运行 相同的查询时,returned json 包含几个反斜杠、转义字符。
代码如下:
SELECT
json_object(
'id', C1.Category1ID,
'text', C1.Category1Name,
'nodes', JSON_ARRAYAGG(
JSON_OBJECT(
'id', C2.Category2ID,
'text', C2.Category2Name,
'nodes', C2.nodes,
'class', 'nav-level-2',
'href', 'admin-categories-2.php'
)
),
'class', 'nav-level-1',
'href', 'admin-categories-1.php'
) AS JSON
FROM categories_1 C1
LEFT JOIN (
SELECT
C2.Category1ID,
C2.Category2ID,
C2.Category2Name,
JSON_ARRAYAGG(
JSON_OBJECT(
'id', C3.Category3ID,
'text', C3.Category3Name,
'class', 'nav-level-3',
'href', 'admin-categories-3.php'
)
) as nodes
FROM categories_2 C2
LEFT JOIN categories_3 C3 ON C3.Category2ID = C2.Category2ID AND C3.Category3Status = 1
WHERE C2.Category2Status = 1
GROUP BY C2.Category2ID
ORDER BY C2.Category2Order, C3.Category3Order
) C2 ON C2.Category1ID = C1.Category1ID
WHERE C1.Category1Status = 1
GROUP BY C1.Category1ID
ORDER BY C1.Category1Order
;
我的问题是如何为 MariaDB 正确编写此查询。
我附上 MySQL (img1) 和 MariaDB (img2) 的结果。
我在此处附加了数据库的创建和插入语句:
CREATE TABLE `categories_1` (
`Category1ID` int(11) NOT NULL AUTO_INCREMENT,
`Category1Name` varchar(45) DEFAULT NULL,
`Category1Name_FR` varchar(45) DEFAULT NULL,
`Category1Photo` varchar(45) DEFAULT NULL,
`Category1Order` int(3) DEFAULT NULL,
`Category1Status` int(1) DEFAULT 1,
PRIMARY KEY (`Category1ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='Top level category'
CREATE TABLE `categories_2` (
`Category2ID` int(11) NOT NULL AUTO_INCREMENT,
`Category2Name` varchar(45) DEFAULT NULL,
`Category2Name_FR` varchar(45) DEFAULT NULL,
`Category2Order` int(3) DEFAULT NULL,
`Category2Status` int(1) DEFAULT 1,
`Category1ID` int(11) DEFAULT NULL COMMENT 'To which parent level category it fits',
PRIMARY KEY (`Category2ID`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='Mid level category'
CREATE TABLE `categories_3` (
`Category3ID` int(11) NOT NULL AUTO_INCREMENT,
`Category3Name` varchar(45) DEFAULT NULL,
`Category3Name_FR` varchar(45) DEFAULT NULL,
`Category3Order` int(3) DEFAULT NULL,
`Category3Status` int(1) DEFAULT 1,
`Category2ID` int(11) DEFAULT NULL COMMENT 'To which parent level category it fits',
PRIMARY KEY (`Category3ID`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COMMENT='Bottom level category'
INSERT INTO `categories_1` VALUES (1,'Meat','Meat-fr','meat.jpg',1,1),(2,'Fish & Sea Food',NULL,'fish.jpg',2,1),(3,'Fruit & Vegetables',NULL,'fruit-veg.jpg',3,1),(4,'Test L1',NULL,'categories-default.jpg',4,0);
INSERT INTO `categories_2` VALUES (1,'Beef','Feef-fr',1,1,1),(2,'Lamb',NULL,2,1,1),(3,'Pork',NULL,3,1,1),(4,'Veal',NULL,4,1,1),(5,'Poultry-Fowl',NULL,6,1,1),(6,'Sausages and Bacon',NULL,5,1,1),(7,'Salmon',NULL,8,1,2),(8,'Flat Fish',NULL,9,1,2),(9,'Common Fish',NULL,10,1,2),(10,'Squid family',NULL,11,1,2),(11,'Shellfish',NULL,12,1,2),(12,'Tuna',NULL,13,1,2),(13,'Other Fish',NULL,14,1,2),(14,'TEST L2',NULL,7,0,1);
INSERT INTO `categories_3` VALUES (1,'Specialist Beef','Specialist Beef-fr',1,1,1),(2,'Wagyu',NULL,2,1,1),(3,'Japanese Wagyu',NULL,3,1,1),(4,'Other Beef',NULL,4,1,1),(5,'All Lamb',NULL,6,1,2),(6,'All Pork',NULL,5,1,3),(7,'All Veal',NULL,7,1,4),(8,'All Poultry-Fowl',NULL,11,1,5),(9,'Pork Sausages',NULL,8,1,6),(10,'Other meats',NULL,9,1,6),(11,'Bacon',NULL,10,1,6),(12,'All Salmon',NULL,12,1,7),(13,'All Flat Fish',NULL,13,1,8),(14,'All Common Fish',NULL,14,1,9),(15,'All Squid family',NULL,15,1,10),(16,'All Shellfish',NULL,16,1,11),(17,'All Tuna',NULL,17,1,12),(18,'All Other Fish',NULL,18,1,13),(19,'TEST L3',NULL,999,0,14);
MariaDB 没有 JSON 数据类型(JSON 关键字只是 LONGTEXT 关键字的别名),它可能只将字符串类型值视为 JSON。
您使用构造JSON_ARRAYAGG( JSON_OBJECT( ...
。在 MariaDB 中,JSON_OBJECT 产生的值是字符串!它是 一个实心字符串 ,而不是 JSON 数据类型的复杂值。因此,在 JSON_ARRAYAGG 期间,处理包含引用所需字符的实心字符串值,并引用所有双引号字符。
参见 FIDDLE,尤其是最后一个和 pre-last 代码块。在 pre-last 块中,特别注意包裹整个值的双引号字符(不是由斜杠引用的内部双引号)。
我没有看到在 MariaDB 中解决这个问题的方法。没有方法告诉函数作为参数提供的值不是字符串而是 JSON - 没有这样的数据类型。
等到 MariaDB 实现 JSON 数据类型 (if) 并升级。