×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

2.1.2. Выражения значений

2.1.2.1. Ссылки на столбцы
2.1.2.2. Позиционные параметры
2.1.2.3. Индексы
2.1.2.4. Выбор поля
2.1.2.5. Вызов оператора
2.1.2.6. Вызовы функций
2.1.2.7. Агрегатные выражения
2.1.2.8. Вызовы оконных функций
2.1.2.9. Приведение типов
2.1.2.10. Выражения правила сортировки
2.1.2.11. Скалярные подзапросы
2.1.2.12. Конструкторы массивов
2.1.2.13. Конструкторы строк
2.1.2.14. Правила вычисления выражений

Выражения значений используются в различных контекстах, например, в списке выбора (target list) команды SELECT команды, в качестве значений новых столбцов в INSERT или UPDATE, или в условиях поиска в ряде команд. Результат выражения значения иногда называют скалярный, чтобы отличить его от результата табличного выражения (которое является таблицей). Таким образом, выражения значения также называют скалярными выражениями (или даже просто выражениями). Синтаксис выражений позволяет вычислять значения из примитивных составляющих с использованием арифметических, логических, теоретико-множественных и других операций.

Выражение значения может принимать одну из следующих форм:

  • Константа или литеральное значение

  • Ссылка на столбец

  • Ссылка на позиционный параметр в теле определения функции или подготовленного оператора

  • Выражение с индексом

  • Выражение выбора поля

  • Вызов оператора

  • Вызов функции

  • Агрегатное выражение

  • Вызов оконной функции

  • Приведение типов

  • Выражение сопоставления

  • Скалярный подзапрос

  • Конструктор массива

  • Конструктор строки

  • Другое выражение значения в скобках (используется для группировки подвыражений и переопределения приоритета)

В дополнение к этому списку существует ряд конструкций, которые могут быть классифицированы как выражения, но не подчиняются никаким общим синтаксическим правилам. Обычно они имеют семантику функции или оператора и описываются в соответствующем разделе в Глава 2.6. Примером является IS NULL предложение.

Константы уже были рассмотрены в Раздел 2.1.1.2. В следующих разделах рассматриваются остальные варианты.

2.1.2.1. Ссылки на столбцы #

Ссылка на столбец может иметь следующий формат:

correlation.columnname

correlation — это имя таблицы (возможно, дополненное именем схемы) или псевдоним таблицы, определенный с помощью FROM предложения. Имя корреляции и разделяющую точку можно опустить, если имя столбца является уникальным во всех таблицах, используемых в текущем запросе. (См. также Глава 2.4.)

2.1.2.2. Позиционные параметры #

Ссылка на позиционный параметр используется для указания значения, которое передается SQL-инструкции извне. Параметры используются в определениях SQL-функций и в подготовленных запросах. Некоторые клиентские библиотеки также поддерживают передачу значений данных отдельно от строки SQL-команды; в этом случае параметры используются для обращения к внешним значениям данных. Формат ссылки на параметр:

$число

Для примера рассмотрим определение функции deptв виде:

CREATE FUNCTION dept(text) RETURNS dept
    AS $$ SELECT * FROM dept WHERE name = $1 $$
    указание LANGUAGE SQL;

Здесь $1 ссылается на значение первого аргумента функции при каждом ее вызове.

2.1.2.3. Индексы #

Если выражение возвращает значение типа массив, то конкретный элемент массива можно извлечь, записав

выражение[индекс]

либо несколько смежных элементов ( «срез массива») можно извлечь, указав

выражение[lower_subscript:upper_subscript]

(Здесь квадратные скобки [ ] должны быть указаны буквально.) Каждый индекс сам является выражением, которое будет округлено до ближайшего целого числа.

В общем случае выражение типа массив выражение должно быть заключено в скобки, однако их можно опустить, если индексируемое выражение представляет собой простую ссылку на столбец или позиционный параметр. Кроме того, можно последовательно указывать несколько индексов, если исходный массив является многомерным. Например:

mytable.arraycolumn[4]
mytable.two_d_column[17][34]
$1[10:42]
(arrayfunction(a,b))[42]

Скобки в последнем примере обязательны. См. Раздел 2.5.15 для получения дополнительной информации о массивах.

2.1.2.4. Выбор поля #

Если выражение возвращает значение составного типа (строкового типа), то конкретное поле строки можно извлечь, указав

выражение.fieldname

В общем случае выражение строки выражение должно быть заключено в скобки, однако их можно опустить, если выражение, из которого выбирается поле, является простой ссылкой на таблицу или позиционным параметром. Например:

mytable.mycolumn
$1.somecolumn
(rowfunction(a,b)).col3

(Таким образом, уточненная ссылка на столбец фактически является лишь частным случаем синтаксиса выбора поля). Важным частным случаем является извлечение поля из столбца таблицы, который имеет составной тип:

(compositecol).somefield
(mytable.compositecol).somefield

В данном случае скобки обязательны, чтобы показать, что compositecol является именем столбца, а не именем таблицы, или что mytable во втором случае является именем таблицы, а не именем схемы.

Для обращения ко всем полям составного значения можно использовать запись .*:

(compositecol).*

Поведение данной нотации зависит от контекста; подробнее см. Раздел 2.5.16.5 для получения подробных сведений.

2.1.2.5. Вызов оператора #

Для вызова оператора предусмотрено два варианта синтаксиса:

выражение оператор выражение (бинарный инфиксный оператор)
оператор выражение (унарный префиксный оператор)

где оператор лексема соответствует синтаксическим правилам Раздел 2.1.1.3, или является одним из ключевых слов AND, OR, и NOT, либо представляет собой квалифицированное имя оператора в формате:

OPERATOR(schema.operatorname)

Доступность конкретных операторов, а также их классификация как унарных или бинарных, зависят от определений, заданных в системе или пользователем. Глава 2.6 описывает встроенные операторы.

2.1.2.6. Вызовы функций #

Синтаксис вызова функции включает в себя имя функции (возможно, уточненное именем схемы), за которым следует список аргументов, заключенный в круглые скобки:

function_name ([выражение [, выражение ... ]] )

Например, следующее выражение вычисляет квадратный корень из 2:

sqrt(2)

Список встроенных функций приведен в Глава 2.6. Другие функции могут быть добавлены пользователем.

При выполнении запросов в базе данных, в которой одни пользователи не доверяют другим, соблюдайте меры предосторожности, описанные в Раздел 2.7.3 при написании вызовов функций.

Аргументам могут быть дополнительно присвоены имена. См. Раздел 2.1.3 для получения подробных сведений.

Примечание

Функция, принимающая единственный аргумент составного типа, может вызываться с использованием синтаксиса выбора поля; и наоборот, выбор поля может быть записан в функциональном стиле. То есть, формы записи col(table) и table.col являются взаимозаменяемыми. Такое поведение не соответствует стандарту SQL, но предусмотрено в Digital Q.DataBase так как оно позволяет использовать функции для эмуляции «вычисляемых полей». Для получения дополнительной информации см. Раздел 2.5.16.5.

2.1.2.7. Агрегатные выражения #

Агрегатное выражение агрегатное выражение представляет собой применение агрегатной функции к строкам, выбранным в результате запроса. Агрегатная функция сводит несколько входных значений к одному выходному значению, такому как сумма или среднее значение входных данных. Синтаксис агрегатного выражения имеет один из следующих видов:

aggregate_name (выражение [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name (ALL выражение [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name (DISTINCT выражение [ , ... ] [ order_by_clause ] ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name ( * ) [ FILTER ( WHERE filter_clause ) ]
aggregate_name ( [ выражение [ , ... ] ] ) WITHIN GROUP ( order_by_clause ) [ FILTER ( WHERE filter_clause ) ]

where aggregate_name является ранее определенной агрегатной функцией (возможно, дополненной именем схемы), и выражение представляет собой любое выражение значения, которое само не содержит агрегатного выражения или вызова оконной функции. Необязательный order_by_clause и filter_clause описаны ниже.

Первая форма агрегатного выражения вызывает агрегат один раз для каждой входной строки. Вторая форма идентична первой, так как ALL используется по умолчанию. Третья форма вызывает агрегатную функцию один раз для каждого уникального значения выражения (или уникального набора значений для нескольких выражений), найденного во входных строках. Четвертая форма вызывает агрегатную функцию один раз для каждой входной строки; поскольку конкретное входное значение не указано, она обычно полезна только для count(*) агрегатная функция. Последняя форма используется с упорядоченными наборами агрегатных функций, которые описаны ниже.

Большинство агрегатных функций игнорируют входные значения null, поэтому строки, в которых одно или несколько выражений принимают значение null, отбрасываются. Это считается верным для всех встроенных агрегатных функций, если не указано иное.

Например, count(*) возвращает общее количество входных строк; count(f1) возвращает количество входных строк, в которых f1 не является null, так как count игнорирует значения null; а count(distinct f1) возвращает количество уникальных значений, отличных от null, в f1.

Обычно входные строки передаются агрегатной функции в неопределенном порядке. Во многих случаях это не имеет значения; например, min выдает один и тот же результат независимо от порядка получения входных данных. Однако некоторые агрегатные функции (такие как array_agg и string_agg) выдают результаты, зависящие от порядка входных строк. При использовании такого агрегата необязательное order_by_clause может использоваться для указания желаемого порядка сортировки. order_by_clause имеет тот же синтаксис, что и для уровня запроса предложение ORDER BY предложение, как описано в Раздел 2.4.5, за исключением того, что его выражения всегда являются обычными выражениями и не могут быть именами или номерами выходных столбцов. Например:

WITH vals (v) AS ( VALUES (1),(3),(4),(3),(2) )
SELECT array_agg(v ORDER BY v DESC) FROM vals;
  array_agg
-------------
 {4,3,3,2,1}

Так как jsonb сохраняет только последний совпадающий ключ, порядок его ключей может иметь значение:

WITH vals (k, v) AS ( VALUES ('key0','1'), ('key1','3'), ('key1','2') )
SELECT jsonb_object_agg(k, v ORDER BY v) FROM vals;
      jsonb_object_agg
----------------------------
 {"key0": "1", "key1": "3"}

При использовании агрегатных функций с несколькими аргументами следует учитывать, что предложение ORDER BY предложение ORDER BY должно следовать за всеми аргументами агрегата. Например, следует писать так:

SELECT string_agg(a, ',' ORDER BY a) FROM table;

а не так:

SELECT string_agg(a ORDER BY a, ',') FROM table;  -- некорректно

Последний вариант синтаксически допустим, но он представляет собой вызов агрегатной функции с одним аргументом и двумя предложение ORDER BY ключами сортировки (второй из которых практически бесполезен, так как является константой).

Если DISTINCT используется вместе с предложением order_by_clause, ORDER BY то выражения могут ссылаться только на те столбцы, которые указаны в списке DISTINCT SELECT. Например:

WITH vals (v) AS ( VALUES (1),(3),(4),(3),(2) )
SELECT array_agg(DISTINCT v ORDER BY v DESC) FROM vals;
 array_agg
-----------
 {4,3,2,1}

Расположение предложение ORDER BY в обычном списке аргументов агрегатной функции, как было описано ранее, используется при упорядочивании входных строк для агрегатов общего назначения и статистических агрегатов, для которых сортировка необязательна. Существует подкласс агрегатных функций, называемых агрегатными функциями упорядоченного набора для которых order_by_clause является обязательным, как правило, потому, что вычисление агрегатной функции имеет смысл только при определенном порядке ее входных строк. Типичными примерами агрегатных функций упорядоченного набора являются расчеты ранга и процентилей. Для агрегатной функции упорядоченного набора предложение order_by_clause записывается внутри WITHIN GROUP (...), как показано в последнем варианте синтаксиса выше. Выражения в предложении order_by_clause вычисляются один раз для каждой входной строки, как и обычные аргументы агрегатной функции, сортируются согласно требованиям order_by_clauseи передаются агрегатной функции в качестве входных аргументов. (Это отличается от правил для не-WITHIN GROUP order_by_clause, которое не рассматривается как аргумент(ы) агрегатной функции.) Выражения аргументов, предшествующие WITHIN GROUP, если таковые имеются, называются прямыми аргументами для их отличия от агрегированных аргументов перечисленных в order_by_clause. В отличие от обычных агрегированных аргументов, прямые аргументы вычисляются только один раз для каждого вызова агрегата, а не для каждой входной строки. Это означает, что они могут содержать переменные только в том случае, если эти переменные сгруппированы с помощью GROUP BY; данное ограничение идентично случаю, когда прямые аргументы находятся вне агрегатного выражения. Прямые аргументы обычно используются для таких величин, как процентильные доли, которые имеют смысл только в качестве единого значения для одного расчета агрегации. Список прямых аргументов может быть пустым; в данном случае следует писать просто () а не (*). (Digital Q.DataBase фактически допускает оба варианта написания, но только первый из них соответствует стандарту SQL.)

Примером вызова агрегатной функции для упорядоченного набора является:

SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY income) FROM households;
 percentile_cont
-----------------
           50489

которая вычисляет значение 50-го процентиля (медиану) дохода столбца таблицы домохозяйства. Здесь 0.5 является прямым аргументом; было бы бессмысленно, если бы значение процентиля менялось от строки к строке.

Если FILTER указано, то агрегатной функции передаются только те входные строки, для которых filter_clause принимает значение true; остальные строки игнорируются. Например:

SELECT
    count(*) AS unfiltered,
    count(*) FILTER (WHERE i < 5) AS filtered
FROM generate_series(1,10) AS s(i);
 unfiltered | filtered
------------+----------
         10 |        4
(1 row)

Предопределенные агрегатные функции описаны в Раздел 2.6.21. Другие агрегатные функции могут быть добавлены пользователем.

Агрегатное выражение может использоваться только в списке результатов или HAVING предложении SELECT команды. Его использование запрещено в других предложениях, таких как WHERE, так как эти предложения логически вычисляются до формирования результатов агрегатов.

Когда агрегатное выражение появляется в подзапросе (см. Раздел 2.1.2.11 и Раздел 2.6.24), агрегат обычно вычисляется по строкам подзапроса. Однако исключение составляют случаи, когда аргументы агрегата (и filter_clause если они есть) содержат только переменные внешнего уровня: в этом случае агрегат относится к ближайшему внешнему уровню и вычисляется по строкам этого запроса. Агрегатное выражение в целом является внешней ссылкой для подзапроса, в котором оно находится, и выступает в качестве константы при каждом выполнении этого подзапроса. Ограничение на появление только в списке результатов или HAVING применяется к тому уровню запроса, к которому относится агрегат.

2.1.2.8. Вызовы оконных функций #

Вызов оконной функции вызов оконной функции представляет собой применение функции, подобной агрегатной, к определенной части строк, выбранных запросом. В отличие от вызовов неоконных агрегатных функций, это не связано с группировкой выбранных строк в одну результирующую строку — каждая строка остается отдельной в выходных данных запроса. Однако оконная функция имеет доступ ко всем строкам, которые входили бы в группу текущей строки согласно спецификации группировки (PARTITION BY списку) вызова оконной функции. Синтаксис вызова оконной функции может принимать одну из следующих форм:

function_name ([выражение [, выражение ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ([выражение [, выражение ... ]]) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER window_name
function_name ( * ) [ FILTER ( WHERE filter_clause ) ] OVER ( window_definition )

где window_definition имеет синтаксис

[ existing_window_name ]
[ PARTITION BY expression [, ...] ]
[ ORDER BY expression [ ASC | DESC | USING оператор ] [ NULLS { FIRST | LAST } ] [, ...] ]
[ frame_clause ]

Необязательный параметр frame_clause может принимать одно из следующих значений

{ RANGE | ROWS | GROUPS } frame_start [ frame_exclusion ]
{ RANGE | ROWS | GROUPS } BETWEEN frame_start AND frame_end [ frame_exclusion ]

где frame_start и frame_end может принимать одно из следующих значений:

UNBOUNDED PRECEDING
смещение PRECEDING
CURRENT ROW
смещение FOLLOWING
UNBOUNDED FOLLOWING

и frame_exclusion может принимать одно из следующих значений:

EXCLUDE CURRENT ROW
EXCLUDE GROUP
EXCLUDE TIES
EXCLUDE NO OTHERS

Здесь выражение представляет собой любое выражение значения, которое само по себе не содержит вызовов оконных функций.

window_name является ссылкой на именованную спецификацию окна, определенную в разделе WINDOW запроса. В качестве альтернативы, полное определение window_definition может быть задано в круглых скобках с использованием того же синтаксиса, который применяется для определения именованного окна в WINDOW см. соответствующую SELECT страницу справочника для получения подробной информации. Стоит отметить, что OVER wname не является в точности эквивалентным OVER (wname ...); последнее подразумевает копирование и изменение определения окна и будет отклонено, если ссылочная спецификация окна содержит предложение определения рамки (frame clause).

Предложение PARTITION BY группирует строки запроса в секции, которые обрабатываются оконной функцией независимо друг от друга. PARTITION BY работает аналогично предложению уровня запроса GROUP BY , за исключением того, что его выражения всегда являются обычными выражениями и не могут быть именами или номерами выходных столбцов. Без PARTITION BY, все строки, возвращаемые запросом, обрабатываются как одна секция. Предложение предложение ORDER BY определяет порядок, в котором строки секции обрабатываются оконной функцией. Оно работает аналогично предложению уровня запроса предложение ORDER BY , но также не может использовать имена или номера выходных столбцов. Без предложение ORDER BY, строки обрабатываются в неопределенном порядке.

Предложение frame_clause определяет набор строк, составляющих рамку окна, которая является подмножеством текущей секции, для тех оконных функций, которые действуют в пределах рамки, а не всей секции. Набор строк во фрейме может изменяться в зависимости от того, какая строка является текущей. Фрейм может быть определен в режиме RANGE, ROWS или GROUPS mode; в каждом случае он охватывает диапазон от frame_start до frame_end. Если значение frame_end опущено, по умолчанию конечной точкой считается CURRENT ROW.

Вызов оконной функции frame_start в значении UNBOUNDED PRECEDING означает, что фрейм начинается с первой строки раздела, и аналогично frame_end в значении UNBOUNDED FOLLOWING означает, что фрейм заканчивается последней строкой раздела.

В RANGE или GROUPS режиме, frame_start CURRENT ROW означает, что рамка начинается с первой строки-соседа строки (строки, которую оконное предложение ORDER BY предложение сортирует как эквивалентную текущей строке), в то время как frame_end CURRENT ROW означает, что рамка заканчивается последней строкой-соседом текущей строки. В ROWS режиме, CURRENT ROW просто означает текущую строку.

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

  • В ROWS режиме, смещение должно возвращать значение, не равное NULL, неотрицательное целое число, и данный параметр означает, что фрейм начинается или заканчивается за указанное количество строк до или после текущей строки.

  • В GROUPS режиме, смещение снова должно возвращать значение, отличное от null, неотрицательное целое число, и данный параметр означает, что фрейм начинается или заканчивается за указанное количество групп родственных строк до или после группы родственных строк для текущей строки, где такая группа — это набор строк, эквивалентных при предложение ORDER BY сортировке. (В определении окна должно присутствовать предложение ORDER BY предложение для использования GROUPS режима.)

  • В RANGE режима, данные параметры требуют, чтобы предложение ORDER BY предложение указывало ровно один столбец. Параметр смещение задает максимальную разность между значением этого столбца в текущей строке и его значением в предшествующих или последующих строках фрейма. Тип данных параметра смещение вид выражения зависит от типа данных столбца сортировки. Для числовых столбцов сортировки оно обычно имеет тот же тип данных, что и сам столбец, но для столбцов сортировки типа дата/время это будет тип interval. Например, если столбец сортировки имеет тип date или timestamp, можно указать RANGE BETWEEN '1 day' PRECEDING AND '10 days' FOLLOWING. Параметр смещение по-прежнему должно быть ненулевым и неотрицательным, хотя смысл понятия ««неотрицательный»» зависит от соответствующего типа данных.

В любом случае расстояние до границы рамки ограничено расстоянием до конца раздела, поэтому для строк, находящихся вблизи границ раздела, рамка может содержать меньше строк, чем в иных случаях.

Обратите внимание, что в обоих ROWS и GROUPS режимах, 0 PRECEDING и 0 FOLLOWING эквивалентны CURRENT ROW. Это обычно справедливо в RANGE режиме также, для соответствующего зависящего от типа данных значения «ноль».

Предложение frame_exclusion параметр позволяет исключать строки вокруг текущей строки из фрейма, даже если они должны быть включены согласно параметрам начала и конца фрейма. EXCLUDE CURRENT ROW исключает текущую строку из фрейма. EXCLUDE GROUP исключает текущую строку и все строки, равные ей при сортировке, из фрейма. EXCLUDE TIES исключает любые строки, равные текущей при сортировке, из фрейма, но не саму текущую строку. EXCLUDE NO OTHERS просто явно определяет поведение по умолчанию: не исключать ни текущую строку, ни равные ей при сортировке строки.

Параметром определения фрейма по умолчанию является RANGE UNBOUNDED PRECEDING, что эквивалентно RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. При наличии предложение ORDER BY, это устанавливает рамку, включающую все строки от начала раздела до последнего предложение ORDER BY родственного элемента (peer) текущей строки. Без предложение ORDER BY, это означает, что все строки раздела включаются в оконную рамку, так как все строки становятся родственными элементами текущей строки.

Ограничения заключаются в том, что frame_start не может быть UNBOUNDED FOLLOWING, frame_end не может быть UNBOUNDED PRECEDING, и параметр frame_end не может стоять в вышеуказанном списке frame_start и frame_end параметров раньше, чем параметр frame_start — например, RANGE BETWEEN CURRENT ROW AND смещение PRECEDING не допускается. Однако, к примеру, ROWS BETWEEN 7 PRECEDING AND 8 PRECEDING допускается, даже если такое условие не выберет ни одной строки.

Если FILTER указано, то агрегатной функции передаются только те входные строки, для которых filter_clause оцениваемые как истинные, передаются в оконную функцию; остальные строки отбрасываются. Только те оконные функции, которые являются агрегатными, принимают FILTER предложение.

Встроенные оконные функции описаны в Таблица 2.6.65. Другие оконные функции могут быть добавлены пользователем. Кроме того, в качестве оконной функции может использоваться любая встроенная или пользовательская агрегатная функция общего назначения или статистический агрегат. (Агрегатные функции упорядоченного набора и гипотетического набора в настоящее время не могут использоваться в качестве оконных функций.)

Синтаксические конструкции с использованием * используются для вызова агрегатных функций без параметров в качестве оконных функций, например count(*) OVER (PARTITION BY x ORDER BY y). Символ «звездочка» (*) обычно не используется для специфических оконных функций. Специфические оконные функции не позволяют использовать DISTINCT или предложение ORDER BY в списке аргументов функции.

Вызовы оконных функций разрешены только в списке SELECT и в предложении предложение ORDER BY запроса.

Дополнительные сведения об оконных функциях можно найти в Раздел 1.3.5, Раздел 2.6.22, и Раздел 2.4.2.5.

2.1.2.9. Приведение типов #

Приведение типов определяет преобразование из одного типа данных в другой. Digital Q.DataBase допускает два эквивалентных синтаксиса для приведения типов:

CAST ( выражение AS тип )
выражение::тип

Предложение CAST синтаксис соответствует стандарту SQL; синтаксис с :: является устаревшим Digital Q.DataBase использование.

Когда приведение применяется к выражению значения известного типа, оно представляет собой преобразование типов во время выполнения. Приведение будет успешным только в том случае, если определена подходящая операция преобразования типов. Обратите внимание, что это несколько отличается от использования приведения с константами, как показано в Раздел 2.1.1.2.7. Приведение, применяемое к простому строковому литералу, представляет собой начальное назначение типа литеральному константному значению, и поэтому оно будет успешным для любого типа (если содержимое строкового литерала является допустимым с точки зрения синтаксиса входных данных для этого типа данных).

Явное приведение типа обычно можно опустить, если нет двусмысленности в отношении типа, который должно возвращать выражение значения (например, когда оно присваивается столбцу таблицы); в таких случаях система автоматически применяет приведение типов. Однако автоматическое приведение выполняется только для тех операций, которые помечены «как допустимые для неявного применения» в системных каталогах. Другие типы приведения должны вызываться с помощью синтаксиса явного приведения. Данное ограничение предназначено для предотвращения скрытого применения непредвиденных преобразований.

Также можно указать приведение типов, используя функциональный синтаксис:

имя_типа ( выражение )

Однако это работает только для типов, имена которых также допустимы в качестве имен функций. Например, double precision нельзя использовать таким образом, но эквивалентный тип float8 можно. Кроме того, имена interval, time, и timestamp могут использоваться в таком виде только в том случае, если они заключены в двойные кавычки, во избежание синтаксических конфликтов. Следовательно, использование функционального синтаксиса приведения типов приводит к несогласованности, и его, вероятно, следует избегать.

Примечание

Функциональный синтаксис фактически представляет собой просто вызов функции. Когда один из двух стандартных вариантов синтаксиса приведения типов используется для преобразования во время выполнения, для выполнения этой операции внутренне вызывается зарегистрированная функция. Согласно принятому соглашению, данные функции преобразования имеют те же имена, что и их выходные типы, и, следовательно, «синтаксис, подобный функциональному,» представляет собой не что иное, как прямой вызов базовой функции преобразования. Очевидно, что переносимому приложению не следует полагаться на данную особенность. Дополнительные сведения см. в разделе CREATE CAST.

2.1.2.10. Выражения правила сортировки #

Предложение COLLATE предложение переопределяет правило сортировки выражения. Оно добавляется к выражению, к которому оно применяется:

expr COLLATE collation

где collation представляет собой идентификатор, который может включать имя схемы. COLLATE предложение имеет более высокий приоритет, чем операторы; при необходимости могут использоваться круглые скобки.

Если правило сортировки не задано явно, система управления базами данных либо определяет его на основе столбцов, задействованных в выражении, либо использует правило сортировки базы данных по умолчанию, если в выражении не участвует ни один столбец.

Двумя основными случаями использования COLLATE предложения являются переопределение порядка сортировки в предложение ORDER BY предложение, например:

SELECT a, b, c FROM tbl WHERE ... ORDER BY a COLLATE "C";

и переопределение сопоставления для вызова функции или оператора, возвращающего результаты с учетом локали, например:

SELECT * FROM tbl WHERE a > 'foo' COLLATE "C";

Обратите внимание, что в последнем случае COLLATE предложение прикрепляется к входному аргументу оператора, на который требуется повлиять. Не имеет значения, к какому именно аргументу оператора или вызова функции прикреплено COLLATE предложение, так как правило сортировки, применяемое оператором или функцией, определяется на основе всех аргументов, а явное COLLATE предложение переопределяет правила сортировки всех остальных аргументов. (Прикрепление несовпадающих COLLATE предложений к нескольким аргументам, однако, является ошибкой. Для получения дополнительной информации см. Раздел 3.8.2.) Таким образом, это дает тот же результат, что и в предыдущем примере:

SELECT * FROM tbl WHERE a COLLATE "C" > 'foo';

Но следующая конструкция ошибочна:

SELECT * FROM tbl WHERE (a > 'foo') COLLATE "C";

поскольку здесь предпринимается попытка применить правило сортировки к результату > оператора, имеющему несопоставимый тип данных boolean.

2.1.2.11. Скалярные подзапросы #

Скалярный подзапрос представляет собой обычный SELECT запрос в скобках, возвращающий ровно одну строку с одним столбцом. (См. Глава 2.4 для получения информации о написании запросов.) Данный SELECT запрос выполняется, и единственное возвращенное значение используется в окружающем выражении значения. Использование запроса, возвращающего более одной строки или более одного столбца в качестве скалярного подзапроса, является ошибкой. (Если же при конкретном выполнении подзапрос не возвращает ни одной строки, ошибка не возникает; скалярный результат считается равным null.) Подзапрос может ссылаться на переменные из внешнего запроса, которые будут выступать константами при каждом отдельном выполнении подзапроса. См. также Раздел 2.6.24 для других выражений, содержащих подзапросы.

Например, следующий запрос находит наибольшую численность населения города в каждом штате:

SELECT name, (SELECT max(pop) FROM cities WHERE cities.state = states.name)
    FROM states;

2.1.2.12. Конструкторы массивов #

Конструктор массива представляет собой выражение, формирующее значение массива на основе значений составляющих его элементов. Простой конструктор массива состоит из ключевого слова ключевое слово ARRAY, левой квадратной скобки [, списка выражений (разделенных запятыми) для значений элементов массива и правой квадратной скобки ]. Например:

SELECT ARRAY[1,2,3+4];
  array
---------
 {1,2,7}
(1 row)

По умолчанию типом элементов массива является общий тип составляющих его выражений, определяемый по тем же правилам, что и для UNION или CASE конструкций (см. Раздел 2.7.5). Это поведение можно переопределить, явно приведя конструктор массива к требуемому типу, например:

SELECT ARRAY[1,2,22.7]::integer[];
  array
----------
 {1,2,23}
(1 row)

Это дает тот же результат, что и приведение каждого выражения к типу элемента массива по отдельности. Подробную информацию о приведении типов см. в разделе Раздел 2.1.2.9.

Многомерные массивы можно создавать путем вложения конструкторов массивов. Во внутренних конструкторах ключевое слово ARRAY ключевое слово ARRAY может быть опущено. Например, следующие команды возвращают одинаковый результат:

SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

SELECT ARRAY[[1,2],[3,4]];
     array
---------------
 {{1,2},{3,4}}
(1 row)

Поскольку многомерные массивы должны быть прямоугольными, внутренние конструкторы на одном уровне должны формировать подмассивы одинаковой размерности. Любое приведение типов, применяемое к внешнему ключевое слово ARRAY конструктор массива распространяется автоматически на все внутренние конструкторы.

Элементами конструктора многомерного массива могут быть любые выражения, возвращающие массив соответствующего типа, а не только под-ключевое слово ARRAY конструкции. Например:

CREATE TABLE arr(f1 int[], f2 int[]);

INSERT INTO arr VALUES (ARRAY[[1,2],[3,4]], ARRAY[[5,6],[7,8]]);

SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr;
                     массив
------------------------------------------------
 {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}
(1 строка)

Можно сконструировать пустой массив, но поскольку массив без указания типа существовать не может, необходимо явно привести пустой массив к требуемому типу. Например:

SELECT ARRAY[]::integer[];
 массив
-------
 {}
(1 строка)

Также конструктор массива можно использовать для формирования массива из результатов подзапроса. В данной форме конструктор массива записывается с использованием ключевого слова ARRAY, ключевое слово ARRAY за которым следует подзапрос в круглых (а не в квадратных) скобках. Например:

SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');
                              массив
------------------------------------------------------------------
 {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31,2412}
(1 row)

SELECT ARRAY(SELECT ARRAY[i, i*2] FROM generate_series(1,5) AS a(i));
              массив
----------------------------------
 {{1,2},{2,4},{3,6},{4,8},{5,10}}
(1 row)

Подзапрос должен возвращать единственный столбец. Если выходной столбец подзапроса имеет тип, не являющийся массивом, то результирующий одномерный массив будет содержать элементы для каждой строки результата подзапроса, а тип элементов будет соответствовать типу выходного столбца подзапроса. Если же выходной столбец подзапроса имеет тип массива, результатом будет массив того же типа, но размерностью на единицу выше; в этом случае все строки подзапроса должны возвращать массивы одинаковой размерности, иначе результат не будет прямоугольным.

Индексы значения массива, созданного с помощью ключевое слово ARRAY всегда начинаются с единицы. Для получения дополнительной информации о массивах см. Раздел 2.5.15.

2.1.2.13. Конструкторы строк #

Конструктор строк — это выражение, которое создает строковое значение (также называемое составным значением), используя значения для составляющих его полей. Конструктор строк состоит из ключевого слова ROW, левой скобки, нуля или более выражений (разделенных запятыми) для значений полей строки и, наконец, правой скобки. Например:

SELECT ROW(1,2.5,'this is a test');

Ключевое слово ROW является необязательным, если в списке более одного выражения.

Конструктор строк может включать синтаксис rowvalue.*, который будет развернут в список элементов строкового значения, точно так же, как это происходит при использовании .* синтаксис используется на верхнем уровне SELECT списка (см. Раздел 2.5.16.5). Например, если таблица t имеет столбцы f1 и f2, следующие выражения эквивалентны:

SELECT ROW(t.*, 42) FROM t;
SELECT ROW(t.f1, t.f2, 42) FROM t;

Примечание

До версии Digital Q.DataBase 8.2, the .* синтаксис не разворачивался в конструкторах строк, поэтому запись ROW(t.*, 42) создавала строку из двух полей, первое поле которой само было строковым значением. Новое поведение обычно более полезно. Если требуется старое поведение с вложенными значениями строк, указывайте внутреннее значение строки без .*, например ROW(t, 42).

По умолчанию значение, создаваемое выражением ROW , относится к анонимному типу record. При необходимости значение можно привести к именованному составному типу — либо к типу строки таблицы, либо к составному типу, созданному с помощью команды CREATE TYPE AS. Для устранения неоднозначности может потребоваться явное приведение типов. Например:

CREATE TABLE mytable(f1 int, f2 float, f3 text);

CREATE FUNCTION getf1(mytable) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- Приведение типа не требуется, так как существует только одна функция getf1()
SELECT getf1(ROW(1,2.5,'this is a test'));
 getf1
-------
     1
(1 row)

CREATE TYPE myrowtype AS (f1 int, f2 text, f3 numeric);

CREATE FUNCTION getf1(myrowtype) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- Теперь требуется приведение типа, чтобы указать, какую функцию вызвать:
SELECT getf1(ROW(1,2.5,'this is a test'));
ERROR:  function getf1(record) is not unique

SELECT getf1(ROW(1,2.5,'this is a test')::mytable);
 getf1
-------
     1
(1 строка)

SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype));
 getf1
-------
    11
(1 строка)

Конструкторы строк могут использоваться для формирования составных значений с целью их сохранения в столбце таблицы составного типа или передачи функции, принимающей составной параметр. Также строки можно проверять с помощью стандартных операторов сравнения, как описано в Раздел 2.6.2, для сравнения одной строки с другой, как описано в Раздел 2.6.25, а также использовать их в сочетании с подзапросами, как описано в Раздел 2.6.24,

2.1.2.14. Правила вычисления выражений #

Порядок вычисления подвыражений не определен. В частности, аргументы оператора или функции не обязательно вычисляются слева направо или в каком-либо ином фиксированном порядке.

Более того, если результат выражения может быть определен путем вычисления лишь некоторых его частей, то другие подвыражения могут не вычисляться вовсе. Например, если указать:

SELECT true OR somefunc();

то somefunc() (вероятно) не будет вызвана вовсе. То же самое произойдет, если написать:

SELECT somefunc() OR true;

Обратите внимание, что это не эквивалентно выполняемому слева направо «сокращенному вычислению» логических операторов, реализованному в некоторых языках программирования.

Как следствие, не рекомендуется использовать функции с побочными эффектами в составе сложных выражений. Особенно опасно полагаться на побочные эффекты или порядок вычисления в WHERE и HAVING предложениях, так как эти предложения существенно перерабатываются в процессе построения плана выполнения. Логические выражения (AND/OR/NOT комбинации) в этих предложениях могут быть реорганизованы любым способом, разрешенным законами булевой алгебры.

В тех случаях, когда необходимо принудительно задать порядок вычисления, может быть использована CASE конструкция (см. Раздел 2.6.18). Например, следующий способ попытки избежать деления на ноль является ненадежным в WHERE предложение:

SELECT ... WHERE x > 0 AND y/x > 1.5;

Однако данный вариант безопасен:

SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;

Вызов оконной функции CASE конструкция, используемая подобным образом, препятствует попыткам оптимизации, поэтому её следует применять только при необходимости. (В данном конкретном примере было бы лучше избежать проблемы, написав y > 1.5*x вместо этого.)

CASE тем не менее не является универсальным решением для подобных проблем. Одно из ограничений вышеописанного метода заключается в том, что он не предотвращает преждевременное вычисление константных подвыражений. Как описано в Раздел 5.1.7, функции и операторы с пометкой IMMUTABLE могут вычисляться на этапе планирования запроса, а не во время его выполнения. Так, например, запрос

SELECT CASE WHEN x > 0 THEN x ELSE 1/0 END FROM tab;

вероятно, приведет к ошибке деления на ноль из-за попытки планировщика упростить константное подвыражение, даже если в каждой строке таблицы значение x > 0 в результате чего ELSE ветвь никогда не будет задействована при выполнении.

Хотя данный конкретный пример может показаться излишним, схожие ситуации, не включающие константы явным образом, могут возникать в запросах внутри функций, поскольку значения аргументов функций и локальных переменных могут подставляться в запросы как константы в целях планирования. В PL/pgSQL функциях, например, использование конструкции IF-THEN-ELSE инструкция для защиты рискованных вычислений гораздо безопаснее, чем простое вложение в CASE выражение.

Другое ограничение того же типа состоит в том, что CASE не может предотвратить вычисление содержащегося в нём агрегатного выражения, так как агрегатные выражения вычисляются перед другими выражениями в SELECT списке или HAVING рассматриваемом предложении. Например, следующий запрос может вызвать ошибку деления на ноль, несмотря на кажущуюся проверку:

SELECT CASE WHEN min(employees) > 0
            THEN avg(expenses / employees)
       END
    FROM departments;

Предложение min() и avg() агрегатные функции вычисляются параллельно для всех входных строк, поэтому, если в какой-либо строке значение employees равно нулю, ошибка деления на ноль возникнет до того, как появится любая возможность проверить результат min(). Вместо этого используйте WHERE или FILTER предложение, чтобы предотвратить попадание проблемных входных строк в агрегатную функцию в первую очередь.

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению