9.16. Функции и операторы JSON #
В этом разделе описываются:
функции и операторы, предназначенные для работы с данными JSON
язык путей SQL/JSON
Postgres Pro реализует модель данных SQL/JSON, обеспечивая встроенную поддержку типов данных JSON в среде SQL. В этой модели данные представляются последовательностями элементов. Каждый элемент может содержать скалярные значения SQL, дополнительно определённое в SQL/JSON значение null и составные структуры данных, образуемые объектами и массивами JSON. Данная модель по сути формализует модель данных, описанную в спецификации JSON RFC 7159.
Поддержка SQL/JSON позволяет обрабатывать данные JSON наряду с обычными данными SQL, используя при этом транзакции, например:
Загружать данные JSON в базу и сохранять их в обычных столбцах SQL в виде символьных или двоичных строк.
Создавать объекты и массивы JSON из реляционных данных.
Обращаться к данным JSON, используя функции запросов SQL/JSON и выражения языка путей SQL/JSON.
Чтобы узнать больше о стандарте SQL/JSON, обратитесь к [sqltr-19075-6]. Типы JSON, поддерживаемые в Postgres Pro, описаны в Разделе 8.14.
9.16.1. Обработка и создание данных JSON #
Примечание
Функции, работающие с JSONB, не принимают символы '\u0000'. Чтобы избежать ошибок и заменять их на лету, необходимо указать символ Unicode в параметре конфигурации unicode_nul_character_replacement_in_jsonb.
В Таблице 9.45 показаны имеющиеся операторы для работы с данными JSON (см. Раздел 8.14). Кроме них для типа jsonb, но не для json, определены обычные операторы сравнения, показанные в Таблице 9.1. Они следуют правилам упорядочивания для операций B-дерева, описанным в Подразделе 8.14.4. В Разделе 9.21 вы также можете узнать об агрегатной функции json_agg, которая агрегирует значения записи в виде JSON, и агрегатной функции json_object_agg, агрегирующей пары значений в объект JSON, а также их аналогах для jsonb, функциях jsonb_agg и jsonb_object_agg.
Таблица 9.45. Операторы для типов json и jsonb
Оператор Описание Пример(ы) |
|---|
Извлекает
|
Извлекает поле JSON-объекта по заданному ключу.
|
Извлекает
|
Извлекает поле JSON-объекта по заданному ключу, в виде значения
|
Извлекает внутренний JSON-объект по заданному пути, элементами которого могут быть индексы массивов или ключи.
|
Извлекает внутренний JSON-объект по заданному пути в виде значения
|
Примечание
Если структура входного JSON не соответствует запросу, например указанный ключ или элемент массива отсутствует, операторы извлечения поля/элемента/пути не выдают ошибку, а возвращают NULL.
Некоторые из следующих операторов существуют только для jsonb, как показано в Таблице 9.46. В Подразделе 8.14.4 описано, как эти операторы могут использоваться для эффективного поиска в индексированных данных jsonb.
Таблица 9.46. Дополнительные операторы jsonb
Оператор Описание Пример(ы) |
|---|
Первое значение JSON содержит второе? (Что означает «содержит», подробно описывается в Подразделе 8.14.3.)
|
Первое значение JSON содержится во втором?
|
Текстовая строка присутствует в значении JSON в качестве ключа верхнего уровня или элемента массива?
|
Какие-либо текстовые строки из массива присутствуют в качестве ключей верхнего уровня или элементов массива?
|
Все текстовые строки из массива присутствуют в качестве ключей верхнего уровня или элементов массива?
|
Соединяет два значения
Чтобы вставить один массив в другой в качестве массива, поместите его в дополнительный массив, например:
|
Удаляет ключ (и его значение) из JSON-объекта или соответствующие строковые значения из JSON-массива.
|
Удаляет из левого операнда все перечисленные ключи или элементы массива.
|
Удаляет из массива элемент в заданной позиции (отрицательные номера позиций отсчитываются от конца). Выдаёт ошибку, если переданное значение JSON — не массив.
|
Удаляет поле или элемент массива с заданным путём, в составе которого могут быть индексы массивов или ключи.
|
Выдаёт ли путь JSON какой-либо элемент для заданного значения JSON?
|
Возвращает результат проверки предиката пути JSON для заданного значения JSON. При этом учитывается только первый элемент результата. Если результат не является логическим, возвращается
|
Примечание
Операторы jsonpath @? и @@ подавляют следующие ошибки: отсутствие поля объекта или элемента массива, несовпадение типа элемента JSON и ошибки в числах и дате/времени. Описанные ниже функции, связанные с jsonpath, тоже могут подавлять ошибки такого рода. Это может быть полезно, когда нужно произвести поиск по набору документов JSON, имеющих различную структуру.
В Таблице 9.47 показаны функции, позволяющие создавать значения типов json и jsonb. Для некоторых функций в этой таблице имеется предложение RETURNING, которое определяет возвращаемый тип данных. Это должен быть json, jsonb, bytea, тип символьной строки (text, char или varchar) или тип, который можно привести к json. По умолчанию возвращается тип json.
Таблица 9.47. Функции для создания JSON
Функция Описание Пример(ы) |
|---|
Преобразует произвольное SQL-значение в
|
Преобразует массив SQL в JSON-массив. Эта функция работает так же, как
|
Создаёт массив JSON либо из набора параметров
|
Преобразует составное значение SQL в JSON-объект. Эта функция работает так же, как
|
Формирует JSON-массив (возможно, разнородный) из переменного списка аргументов. Каждый аргумент преобразуется методом
|
Формирует JSON-объект из переменного списка аргументов. По соглашению в этом списке перечисляются по очереди ключи и значения. Аргументы, задающие ключи, приводятся к текстовому типу, а аргументы-значения преобразуются методом
|
Создаёт объект JSON из всех заданных пар ключ/значение или пустой объект, если ни одна пара не задана. В аргументе
|
Формирует объект JSON из текстового массива. Этот массив должен иметь либо одну размерность с чётным числом элементов (в этом случае они воспринимаются как чередующиеся ключи/значения), либо две размерности и при этом каждый внутренний массив содержит ровно два элемента, которые воспринимаются как пара ключ/значение. Все значения преобразуются в строки JSON.
|
Эта форма
|
Преобразует выражение, заданное в виде строки типа
|
Преобразует заданное скалярное значение SQL в скалярное значение JSON. Если передаётся NULL, возвращается SQL NULL. Если передаётся число или логическое значение, возвращается соответствующее числовое или логическое значение JSON. Для любого другого значения возвращается строка JSON.
|
Преобразует выражение SQL/JSON в символьную или двоичную строку. Аргумент
|
В Таблице 9.48 описаны средства SQL/JSON для проверки JSON.
Таблица 9.48. Функции проверки SQL/JSON
В Таблице 9.49 показаны функции, предназначенные для работы со значениями json и jsonb.
Таблица 9.49. Функции для обработки JSON
Функция Описание Пример(ы) |
|---|
Разворачивает JSON-массив верхнего уровня в набор значений JSON.
value ----------- 1 true [2,false] |
Разворачивает JSON-массив верхнего уровня в набор значений
value ----------- foo bar |
Возвращает число элементов во внешнем JSON-массиве верхнего уровня.
|
Разворачивает JSON-объект верхнего уровня в набор пар ключ/значение (key/value).
key | value -----+------- a | "foo" b | "bar" |
Разворачивает JSON-объект верхнего уровня в набор пар ключ/значение (key/value). Возвращаемые значения будут иметь тип
key | value -----+------- a | foo b | bar |
Извлекает внутренний JSON-объект по заданному пути. (То же самое делает оператор
|
Извлекает внутренний JSON-объект по заданному пути в виде значения
|
Выдаёт множество ключей в JSON-объекте верхнего уровня.
json_object_keys ----------------- f1 f2 |
Разворачивает JSON-объект верхнего уровня в строку, имеющую составной тип аргумента Для преобразования значения JSON в SQL-тип выходного столбца последовательно применяются следующие правила:
В следующем примере значение JSON фиксировано, но обычно такая функция обращается с использованием
a | b | c
---+-----------+-------------
1 | {2,"a b"} | (4,"a b c") |
Разворачивает JSON-массив верхнего уровня с объектами в набор строк, имеющих составной тип аргумента
a | b ---+--- 1 | 2 3 | 4 |
Разворачивает JSON-объект верхнего уровня в строку, имеющую составной тип, определённый в предложении
a | b | c | d | r
---+---------+---------+---+---------------
1 | [1,2,3] | {1,2,3} | | (123,"a b c") |
Разворачивает JSON-массив верхнего уровня с объектами в набор строк, имеющих составной тип, определённый в предложении
a | b ---+----- 1 | foo 2 | |
Возвращает объект
|
Если значение
|
Возвращает объект
|
Удаляет из данного значения JSON все поля объектов, имеющие значения null, на всех уровнях вложенности. Значения null, не относящиеся к полям объектов, сохраняются без изменений.
|
Проверяет, есть ли в заданном значении JSON какой-либо элемент, соответствующий пути JSON. В случае присутствия аргумента
|
Возвращает результат проверки предиката пути JSON для заданного значения JSON. При этом учитывается только первый элемент результата. Если результат не является логическим, возвращается
|
Возвращает все элементы JSON, полученные по указанному пути для заданного значения JSON. Дополнительные аргументы
jsonb_path_query ------------------ 2 3 4 |
Возвращает все элементы JSON, полученные по указанному пути для заданного значения JSON, в виде JSON-массива. Дополнительные аргументы
|
Возвращает первый элемент JSON, полученный по указанному пути для заданного значения JSON, либо NULL, если этому пути не соответствуют никакие элементы. Дополнительные аргументы
|
Эти функции работают подобно их двойникам без суффикса
|
Преобразует данное значение JSON в визуально улучшенное текстовое представление с отступами.
[
{
"f1": 1,
"f2": null
},
2
] |
Возвращает тип значения на верхнем уровне JSON в виде текстовой строки. Возможные типы:
|
В Таблице 9.50 описаны функции SQL/JSON, которые можно использовать для обращения к данным JSON.
Примечание
Пути SQL/JSON можно применять только к типу jsonb, поэтому аргумент элемент_контекста этих функций, возможно, потребуется привести к типу jsonb.
Таблица 9.50. Функции запросов SQL/JSON
9.16.2. JSON_TABLE #
json_table — это функция SQL/JSON, которая обрабатывает данные JSON и выдаёт результаты в виде реляционного представления, к которому можно обращаться как к обычной таблице SQL. Использовать json_table можно только внутри предложения FROM оператора SELECT.
Принимая данные JSON, функция json_table обрабатывает выражение пути и извлекает часть представленных данных, которая будет использоваться в качестве шаблона строк для создаваемого представления. Каждый элемент SQL/JSON на верхнем уровне шаблона строк служит источником для отдельной строки в создаваемом реляционном представлении.
Для разделения шаблона строк на столбцы в функции json_table применяется предложение COLUMNS, определяющее схему создаваемого представления. В этом предложении для каждого создаваемого столбца задаётся отдельное выражение пути, обрабатывающее шаблон строк, извлекающее элемент JSON и возвращающее его в виде отдельного значения SQL для данного столбца. Если требуемое значение находится на вложенном уровне шаблона строк, его можно извлечь, используя вложенное предложение NESTED PATH. При объединении столбцов, возвращаемых NESTED PATH, в создаваемом представлении могут добавиться несколько новых строк. Такие строки называются дочерними строками, а строка, которая их создаёт, — родительской строкой.
Строки, формируемые функцией JSON_TABLE, соединяются как последующие (LATERAL) со строкой, из которой они сформированы, поэтому нет необходимости явно соединять создаваемое представление с исходной таблицей, содержащей данные JSON. При этом, используя предложение PLAN, можно определить, как соединять столбцы, которые возвращает NESTED PATH.
Каждое предложение NESTED PATH может создать один или несколько столбцов. Столбцы, созданные NESTED PATH на одном уровне, считаются соседними; при этом столбцы, созданные вложенным выражением NESTED PATH, считаются потомками столбца, сформированного другим выражением NESTED PATH или выражением строки на более высоком уровне. При формировании результата сначала вместе составляются соседние столбцы, а после этого полученные строки соединяются с родительской строкой.
Синтаксис:
JSON_TABLE (элемент_контекста,выражение_пути[ASимя_пути_json] [PASSING {значениеASимя_переменной} [, ...]] COLUMNS (столбец_таблицы_json[, ...] ) [{ERROR|EMPTY}ON ERROR] [PLAN (план_таблицы_json) | PLAN DEFAULT ( { INNER | OUTER } [, { CROSS | UNION }] | { CROSS | UNION } [, { INNER | OUTER }] )] ) Здесьстолбец_таблицы_json:имятип[PATHописание_пути_json] [{ WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ARRAY] WRAPPER] [{ KEEP | OMIT } QUOTES [ON SCALAR STRING]] [{ ERROR | NULL | DEFAULTвыражение} ON EMPTY] [{ ERROR | NULL | DEFAULTвыражение} ON ERROR] |имятипFORMATпредставление_json[PATHописание_пути_json] [{ WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ARRAY] WRAPPER] [{ KEEP | OMIT } QUOTES [ON SCALAR STRING]] [{ ERROR | NULL | EMPTY { ARRAY | OBJECT } | DEFAULTвыражение} ON EMPTY] [{ ERROR | NULL | EMPTY { ARRAY | OBJECT } | DEFAULTвыражение} ON ERROR] |имятипEXISTS [PATHописание_пути_json] [{ ERROR | TRUE | FALSE | UNKNOWN } ON ERROR] | NESTED PATHописание_пути_json[ASимя_пути] COLUMNS (столбец_таблицы_json[, ...] ) |имяFOR ORDINALITY здесьплан_таблицы_json:имя_пути_json[{ OUTER | INNER }первичный_план_таблицы_json] |первичный_план_таблицы_json{ UNIONпервичный_план_таблицы_json} [...] |первичный_план_таблицы_json{ CROSSпервичный_план_таблицы_json} [...] здесьпервичный_план_таблицы_json:имя_пути_json| (план_таблицы_json)
Каждый элемент синтаксиса описан ниже более подробно.
-
элемент_контекста,выражение_пути[ASимя_пути_json] [PASSING{значениеASимя_переменной} [, ...]] Входные данные для запроса, выражение пути JSON, определяющее запрос, и необязательное предложение
PASSING, которое может предоставлять значения данных длявыражения_пути. Результат обработки входных данных называется шаблоном строк. Шаблон строк используется в качестве источника для значений строк в создаваемом представлении.COLUMNS(столбец_таблицы_json[, ...] )Предложение
COLUMNS, определяющее схему создаваемого представления. В этом предложении должны указываться все столбцы, в которые будут помещаться элементы SQL/JSON. Выражениестолбец_таблицы_jsonимеет следующие варианты синтаксиса:-
имятип[PATHописание_пути_json] Вставляет один элемент SQL/JSON во все строки с указанным столбцом.
Если заданное выражение
PATHвычисляется, столбец заполняется сформированными элементами SQL/JSON (по одному в строке). Если выражениеPATHопускается, функцияJSON_TABLEвычисляет выражение пути$., гдеимяимя— указанное имя столбца. В этом случае имя столбца должно соответствовать одному из ключей в элементе SQL/JSON, созданном шаблоном строк.Также можно добавить предложения
ON EMPTYиON ERROR, чтобы определить, как обрабатывать отсутствующие значения или структурные ошибки. ПредложенияWRAPPERиQUOTESможно использовать только с типами JSON, массивами и составными типами. Эти предложения имеют тот же синтаксис и семантику, что и вjson_valueиjson_query.-
имятипFORMATпредставление_json[PATHописание_пути_json] Создаёт столбец и вставляет составной элемент SQL/JSON во все строки с указанным столбцом.
Если заданное выражение
PATHвычисляется, столбец заполняется сформированными элементами SQL/JSON (по одному в строке). Если выражениеPATHопускается, функцияJSON_TABLEвычисляет выражение пути$., гдеимяимя— указанное имя столбца. В этом случае имя столбца должно соответствовать одному из ключей в элементе SQL/JSON, созданном шаблоном строк.Также можно добавить предложения
WRAPPER,QUOTES,ON EMPTYиON ERROR, чтобы определить дополнительные параметры для возвращаемых элементов SQL/JSON. Эти предложения имеют тот же синтаксис и семантику, что и вjson_query.-
имятипEXISTS[PATHописание_пути_json] Создаёт столбец и вставляет логический элемент во все строки с указанным столбцом.
Если заданное выражение
PATHвычисляется, проводится проверка того, были ли получены соответствующие элементы SQL/JSON, и столбец заполняется логическими значениями (по одному в каждой строке). Для заданного типаtypeдолжно существовать приведение изboolean. Если выражениеPATHопускается, функцияJSON_TABLEвычисляет выражение пути$., гдеимяимя— указанное имя столбца.Также можно добавить предложение
ON ERROR, чтобы определить поведение при ошибке. Это предложение имеет тот же синтаксис и семантику, что и вjson_exists.NESTED PATHописание_пути_json[ASимя_пути_json]COLUMNS(столбец_таблицы_json[, ...] )Извлекает элементы SQL/JSON из вложенных уровней шаблона строк, создаёт один или несколько столбцов, как определено во вложенном предложении
COLUMNS, и вставляет извлечённые элементы SQL/JSON во все строки с этими столбцами. Выражениестолбец_таблицы_jsonво вложенном предложенииCOLUMNSимеет тот же синтаксис, что и в родительском предложенииCOLUMNS.Синтаксис
NESTED PATHявляется рекурсивным, поэтому вкладывая одно предложениеNESTED PATHв другое, можно опускаться ниже от уровня к уровню. Это позволяет развернуть иерархию объектов и массивов JSON в одном вызове функции, а не связывать несколько выраженийJSON_TABLEв операторе SQL.Используя предложение
PLAN, можно определить, как объединять столбцы, возвращаемые предложениямиNESTED PATH.-
имяFOR ORDINALITY Добавляет столбец, обеспечивающий последовательную нумерацию строк. В таблице может быть только один столбец нумерации. Нумерация строк начинается с единицы. Для дочерних строк, сформированных предложениями
NESTED PATH, повторяется номер родительской строки.
-
-
ASимя_пути_json Необязательный параметр
имя_пути_jsonслужит идентификатором заданного параметраописание_пути_json. Имя пути должно быть уникальным и отличаться от имён столбцов. Когда применяется предложениеPLAN, необходимо задать имена для всех путей, включая шаблон строк. Имена путей в предложенииPLANне могут повторяться.PLAN(план_таблицы_json)Определяет, как соединять данные, возвращаемые предложениями
NESTED PATH, с создаваемым представлением.Соединять столбцы, реализуя отношения родитель/потомок, можно следующими способами:
-
INNER Используйте
INNER JOIN, чтобы родительская строка была исключена из вывода, если для неё не нашлось дочерних строк при объединении с данными, возвращённымиNESTED PATH.-
OUTER Используйте
LEFT OUTER JOIN, чтобы родительская строка всегда включалась в вывод, даже если для неё не нашлось дочерних строк при объединении с данными, возвращённымиNESTED PATH. Если соответствующие значения отсутствуют, в дочерние столбцы будут вставлены значения NULL.По умолчанию для соединения столбцов используется этот вариант.
Соединять соседние столбцы можно следующими способами:
-
UNION Сгенерировать одну строку для каждого значения отдельного соседнего столбца. Соседи данного столбца при этом заполняются значениями NULL.
Этот вариант выбирается по умолчанию для соединения соседних столбцов.
-
CROSS Сгенерировать одну строку для каждой комбинации значений из соседних столбцов.
-
PLAN DEFAULT()OUTER | INNER[,UNION | CROSS]Эти указания могут также задаваться в обратном порядке. В этом случае
INNERилиOUTERопределяет план соединения родительских/дочерних столбцов, аUNIONилиCROSSвлияет на объединение соседних столбцов. ФормаPLAN DEFAULTпереопределяет план по умолчанию для всех столбцов сразу. Несмотря на то, что в формеPLAN DEFAULTимена путей не указываются, для соответствия стандарту SQL/JSON имена должны задаваться для всех путей, если используется предложениеPLAN.Использовать
PLAN DEFAULTпроще, чем указывать полныйPLAN, и зачастую этого достаточно для получения желаемого результата.
Примеры
В этих примерах будет использоваться следующая небольшая таблица