Я протестировал следующее с MySQL 8.0. Он использует функции, которые, по-видимому, присутствуют в MariaDB согласно его документации, но у меня нет экземпляра MariaDB для тестирования.
SELECT * FROM mytable;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| data |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| {"1": {"text": "Item1", "value": 1, "isActive": 0, "textDisplay": ""}, "2": {"text": "Item2", "value": 2, "isActive": 1, "textDisplay": ""}, "3": {"text": "Item3", "value": 3, "isActive": 1, "textDisplay": ""}, "nextValue": 4} |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
SELECT JSON_UNQUOTE(JSON_EXTRACT(JSON_EXTRACT(data, REPLACE(JSON_UNQUOTE(JSON_SEARCH(data, 'one', 'Item2')), '.text', '')), '$.value')) AS value FROM mytable;
+-------+
| value |
+-------+
| 2 |
+-------+
Это невероятно хрупкий процесс, основанный на замене строк в путях JSON и последующем использовании этих путей в дальнейших функциях JSON. Разработка и поддержка таких сложных операторов SQL потребует у вашего работодателя много рабочих часов.
Альтернативой может быть обновление до MySQL 8.0 и использование функции JSON_TABLE () для отображения вашего документа JSON в производную таблицу, тогда вы можете использовать условия в предложении WHERE.
SELECT j.* FROM mytable2,
JSON_TABLE(mytable2.data, '$[*]'
COLUMNS (
rowid FOR ORDINALITY,
`text` VARCHAR(20) PATH '$.text',
textDisplay TEXT PATH '$.textDisplay',
value INT PATH '$.value',
isActive BOOL PATH '$.isActive'
)
) AS j
+-------+-------+-------------+-------+----------+
| rowid | text | textDisplay | value | isActive |
+-------+-------+-------------+-------+----------+
| 1 | Item1 | | 1 | 0 |
| 2 | Item2 | | 2 | 1 |
| 3 | Item3 | | 3 | 1 |
+-------+-------+-------------+-------+----------+
Но это не сработает с данными JSON, которые у вас есть, потому что функция работает, только если ваш JSON является массивом, тогда как ваши данные отформатированы как объект JSON. Приведенный выше пример работал, только когда я изменил формат данных JSON на массив:
select * from mytable2;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| data |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| [{"text": "Item1", "value": 1, "isActive": 0, "textDisplay": ""}, {"text": "Item2", "value": 2, "isActive": 1, "textDisplay": ""}, {"text": "Item3", "value": 3, "isActive": 1, "textDisplay": ""}] |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Формат JSON, разработанный вашими разработчиками, позволяет им легко вставлять данные, но это совершенно бесплатное использование JSON и делает запросы к данным излишне сложными. Это пример эффекта внутренней платформы :
Эффект внутренней платформы - это тенденция архитекторов программного обеспечения создавать систему, настраиваемую так, чтобы она стала копией, а часто и плохой копией платформы разработки программного обеспечения, которую они используют. Как правило, это неэффективно, и такие системы часто считаются примерами анти-паттерна.
Как я уже говорил выше, я бы разработал это как обычную таблицу SQL:
CREATE TABLE Items (
id INT AUTO_INCREMENT PRIMARY KEY,
`text` VARCHAR(20),
textDisplay TEXT,
value INT,
isActive BOOL
);
Заполните его значениями в каждом столбце:
INSERT INTO Items
VALUES (1, 'Item1', '', 1, 0),
(2, 'Item2', '', 2, 1),
(3, 'Item3', '', 3, 1);
Тогда вы можете запросить его очень просто:
SELECT value FROM Items WHERE `text` = 'Item2';
+-------+
| value |
+-------+
| 2 |
+-------+
Ваш работодатель должен предпочесть простоту хранения данных обычным способом, потому что он сэкономит много времени и денег, когда придет время запрашивать данные.