Как использовать скалярный подзапрос в предложении значения Db2 JSON_OBJECT?

#sql #json #db2

#sql #json #db2

Вопрос:

Я пытаюсь создать JSON_OBJECT() из скалярного подзапроса, подобного этому, в Db2 LUW v11.5.4.0:

 SELECT
  JSON_OBJECT(KEY 'x' VALUE (SELECT 1 FROM sysibm.dual))
FROM sysibm.dual;
  

Это приводит к

После «1 из sysibm.dual)» был обнаружен неожиданный токен «)». Ожидаемые токены могут включать: «<интервал_квалификатор>».. SQLCODE=-104, SQLSTATE= 42601, DRIVER= 4.26.14

Аналогичный запрос работает в Oracle, и из документации я не вижу, что я делаю неправильно в Db2. Как я могу построить a JSON_OBJECT() из скалярного подзапроса?

Ответ №1:

Эти хаки и, возможно, другие, похоже, работают:

 SELECT
  JSON_OBJECT(KEY 'x' VALUE COALESCE(NULL, (SELECT 1 FROM sysibm.dual)))
FROM sysibm.dual;

SELECT
  JSON_OBJECT(KEY 'x' VALUE DECODE(1, 1, (SELECT 1 FROM sysibm.dual)))
FROM sysibm.dual;
  

Комментарии:

1. То есть вы просто копируете содержимое редактирования Лукаша в новый ответ и помечаете его как решение?

2. Дорогой @Anho, большое вам спасибо за ваш очень внимательный комментарий. 1) это не копия ответа Лукаша, пожалуйста, внимательно просмотрите наши ответы. 2) Сначала я написал свой ответ, пожалуйста, внимательно посмотрите на временные метки. Лукаш был так любезен, что дополнил мои предложения другими вариантами. 3) Пожалуйста, не предполагайте зла, пока не будете полностью уверены.

3. Вы правы. Извините. Во время публикации ваш комментарий был вторым, и я ошибочно предположил, что записи упорядочены по времени создания. Я действительно должен был проверить дальше.

4. @Anho: Не беспокойтесь. Кстати, в Stack Overflow рекомендуется отвечать на собственные вопросы, чтобы поделиться знаниями. Я уже знал ответ, когда опубликовал «вопрос»…

Ответ №2:

Я бы переместил скалярный подзапрос из SELECT списка в LATERAL часть, которая будет точным эквивалентом. Это также должно удовлетворять синтаксическому анализатору:

 SELECT JSON_OBJECT(KEY 'x' VALUE my_scalar)
FROM sysibm.dual, LATERAL(SELECT 1 AS my_scalar FROM sysibm.dual);
  

db<>демонстрация скрипки


Редактировать:

Взломать с помощью функции:

 SELECT JSON_OBJECT(KEY 'x' VALUE MAX((SELECT 1 FROM sysibm.dual)))
FROM sysibm.dual;
  

Здесь MAX , потому что он принимает один аргумент и не изменяет тип данных (такой же, как COALESCE / DECODE ).

Комментарии:

1. Интересная идея. В моем случае ( поддержка JSON_OBJECT jOOQ ) это будет непрактично, потому что при перемещении выражения из SELECT (или ORDER BY WHERE , и т.д.) в FROM предложение слишком много предостережений. Например, семантика звездочки * изменится, также псевдоним боковой производной таблицы и синтетического столбца может привести к конфликтам. Но приятно видеть, что это обходное решение тоже работает — это означает, что на самом деле это просто ошибка синтаксического анализатора.

2. @LukasEder Да, тогда ваш подход с предоставлением выражения (вызова функции) является лучшим. Я мог бы предложить MAX (не агрегированный, а скорее GREATEST эквивалентный).

3. Интересно, я не знал эту функцию. Может быть интересно изучить в целом!

4. @LukasEder Похоже MAX/MIN , у него есть свои причуды из-за того, что он использует одно и то же имя с agg function. db<>fiddle demo . COALESCE Кажется, что оставаться с ним — самый безопасный вариант.