PostgreSQL - оператор CAST vs :: для LATERAL табличной функции

Nov 27 2020

Пока я могу

SELECT elem[1], elem[2]
FROM   ( VALUES ('1,2'::TEXT) ) AS q(arr),
       LATERAL CAST(String_To_Array(q.arr, ',') AS INT[]) AS elem
;

используя явный вызов CAST, я не могу

SELECT elem[1], elem[2]
FROM   ( VALUES ('1,2'::TEXT) ) AS q(arr),
       LATERAL String_To_Array(q.arr, ',')::INT[] AS elem
;

используя неявно вызывающий ::оператор:

ОШИБКА: синтаксическая ошибка около "::" или около него.

Еще одно место, в котором требуется явное указание CAST:

CREATE INDEX ON ... ( CAST(<straw> AS <gold>) );

Я сомневаюсь, что есть синтаксическая причина, например, использование дополнительных скобок, что здесь неверно.

На данном этапе просто необходим явный вызов функции как часть низкоуровневой реализации? Или это соответствует каким-то языковым правилам?

Ответы

5 ErwinBrandstetter Nov 27 2020 at 11:35

Отличные примеры угловых корпусов. Оба этих варианта синтаксиса представляют собой «явное приведение типов», выполняя одно и то же. Так уж получилось, что некоторые специальные места в коде SQL позволяют только функциональную нотацию, чтобы избежать двусмысленности.

Что касается вашего второго наблюдения:

Еще одно место, в котором требуется явное указание CAST:

CREATE INDEX ON ... ( CAST(<straw> AS <gold>) );

Здесь действительно можно использовать сокращенный синтаксис - с дополнительным набором круглых скобок, чтобы сделать его однозначным:

CREATE INDEX ON ... ((<straw>::<gold>));

db <> скрипка здесь

И любой вариант синтаксиса также соответствует другому выражению в запросах. Видеть:

  • Можем ли мы создать индекс для ключа / значения типа данных JSONB?
  • Как создать индекс для целочисленного свойства json в postgres
  • Разделение даты и времени на 2 столбца для схемы бронирования ресторана?

(Есть более эффективные способы сделать то, что делает ваш первый пример, но, вероятно, это не имеет значения.)

5 LaurenzAlbe Nov 27 2020 at 10:27

Да, это немного странно, но грамматика будет принимать только что-то синтаксически похожее на вызов функции в выражении function-in-FROM.

Так что это действительно уловка, которую вы можете использовать, если вам нужно произвольное выражение в FROMпредложении: окружите его ненужным CASTвыражением.

PostgreSQL с радостью будет рассматривать все, что выглядит как функция, как табличная функция в таком контексте.