Иллюстрированный самоучитель по PostgreSQL › Краткий курс SQL › Преобразование типов [страница — 54] | Самоучители по программированию
Преобразование типов
В PostgreSQL поддерживаются три отдельных варианта синтаксиса преобразования (приведения) типов, то есть механизма приведения данных от одного типа к другому. В команде SQL преобразование типов позволяет явно задать тип создаваемой константы (вместо его косвенного определения по правилам языка).
В общем случае приведение строковой константы к другому типу может выполняться любым из трех способов:
тип 'значение' 'значение': – . тип CAST ('значение' AS тип)
Числовые константы преобразуются в символьную строку следующими способами:
значение:: тип CAST (значение AS тип)
Здесь значение представляет константу, тип которой требуется изменить, а тип – новый тип этой константы.
Примечание
Помните, что тип money считается устаревшим, что несколько затрудняет его использование в преобразованиях.
Преобразование к другому типу данных не ограничивается одними константами. Поля набора данных, возвращаемого запросом SQL, также могут преобразовываться к другому типу, при этом используются следующие формы синтаксиса:
идентификатор:: тип CAST (идентификатор AS тип)
Следует учесть, что не каждый тип данных может быть приведен к любому другому типу. Например, не существует осмысленного преобразования символьной строки abed в двоичную последовательность типа bit. Недопустимые попытки преобразования приводят к ошибкам PostgreSQL. Чаще всего встречаются преобразования символьных строк, типов даты/времени или числовых типов к типу text, а также символьных строк в числа.
Кроме синтаксических форм преобразования типа существуют некоторые функции, позволяющие добиться практически того же результата. Имена этих функций часто совпадают с именами итоговых типов (например, text()), хотя существуют и узкоспециализированные варианты (например, bitfromint4()). В листинге 3.30 приведен пример использования функции text () для преобразования целого числа 1000 в строку типа text, содержащую символы «1000».
Листинг 3.30. Использование функции преобразования типа.
booktown=# SELECT text(1000) booktown-# AS explicitjtext; explicit_text
samoychiteli.ru
PostgreSQL : Документация: 9.6: 10.1. Обзор : Компания Postgres Professional
SQL — язык со строгой типизацией. То есть каждый элемент данных в нём имеет некоторый тип, определяющий его поведение и допустимое использование. PostgreSQL наделён расширяемой системой типов, более универсальной и гибкой по сравнению с другими реализациями SQL. При этом преобразования типов в PostgreSQL в основном подчиняются определённым общим правилам, для их понимания не нужен эвристический анализ. Благодаря этому в выражениях со смешанными типами можно использовать даже типы, определённые пользователями.
Анализатор выражений PostgreSQL разделяет их лексические элементы на пять основных категорий: целые числа, другие числовые значения, текстовые строки, идентификаторы и ключевые слова. Константы большинства не числовых типов сначала классифицируются как строки. В определении языка SQL допускается указывать имена типов в строках и это можно использовать в PostgreSQL, чтобы направить анализатор по верному пути. Например, запрос:
SELECT text 'Origin' AS "label", point '(0,0)' AS "value"; label | value --------+------- Origin | (0,0) (1 row)
содержит две строковых константы, типа text
и типа point
. Если для такой константы не указан тип, для неё первоначально предполагается тип unknown
, который затем может быть уточнён, как описано ниже.
В SQL есть четыре фундаментальных фактора, определяющих правила преобразования типов для анализатора выражений PostgreSQL:
- Вызовы функций
Система типов PostgreSQL во многом построена как дополнение к богатым возможностям функций. Функции могут иметь один или несколько аргументов, и при этом PostgreSQL разрешает перегружать имена функций, так что имя функции само по себе не идентифицирует вызываемую функцию; анализатор выбирает правильную функцию в зависимости от типов переданных аргументов.
- Операторы
PostgreSQL позволяет использовать в выражениях префиксные и постфиксные операторы с одним аргументом, а также операторы с двумя аргументами. Как и функции, операторы можно перегружать, так что и с ними существует проблема выбора правильного оператора.
- Сохранение значений
SQL-операторы
INSERT
иUPDATE
помещают результаты выражений в таблицы. При этом получаемые значения должны соответствовать типам целевых столбцов или, возможно, приводиться к ним.UNION
,CASE
и связанные конструкцииТак как все результаты запроса объединяющего оператора
SELECT
должны оказаться в одном наборе столбцов, результаты каждого подзапросаSELECT
должны приводиться к одному набору типов. Подобным образом, результирующие выражения конструкции
должны приводиться к общему типу, так как выражениеCASE
в целом должно иметь определённый выходной тип. То же справедливо в отношении конструкцийARRAY
и функцийGREATEST
иLEAST
.
Информация о существующих преобразованиях или приведениях типов, для каких типов они определены и как их выполнять, хранится в системных каталогах. Пользователь также может добавить дополнительные преобразования с помощью команды CREATE CAST. (Обычно это делается, когда определяются новые типы данных. Набор приведений для встроенных типов достаточно хорошо проработан, так что его лучше не менять.)
Дополнительная логика анализа помогает выбрать оптимальное приведение в группах типов, допускающих неявные преобразования. Для этого типы данных разделяются на несколько базовых категорий, которые включают: boolean
, numeric
string
, bitstring
, datetime
, timespan
, geometric
, network
и пользовательские типы. (Полный список категорий приведён в Таблице 50.56; хотя его тоже можно расширить, определив свои категории.) В каждой категории могут быть выбраны один или несколько предпочитаемых типов, которые будут считаться наиболее подходящими при рассмотрении нескольких вариантов. Аккуратно выбирая предпочитаемые типы и допустимые неявные преобразования, можно добиться того, что выражения с неоднозначностями (в которых возможны разные решения задачи преобразования) будут разрешаться наилучшим образом.Все правила преобразования типов разработаны с учётом следующих принципов:
Результат неявных преобразованиях всегда должен быть предсказуемым и понятным.
Если в неявном преобразовании нет нужды, анализатор и исполнитель запроса не должны тратить лишнее время на это. То есть, если запрос хорошо сформулирован и типы значений совпадают, он должен выполняться без дополнительной обработки в анализаторе и без лишних вызовов неявных преобразований.
Кроме того, если запрос изначально требовал неявного преобразования для функции, а пользователь определил новую функцию с точно совпадающими типами аргументов, анализатор должен переключиться на новую функцию и больше не выполнять преобразование для вызова старой.
postgrespro.ru
Postgres Pro Standard : Документация: 9.5: 9.8. Функции форматирования данных : Компания Postgres Professional
FM
подавляет дополняющие пробелы и нули справа, которые в противном случае будут добавлены, чтобы результат имел фиксированную ширину. В Postgres Pro модификатор FM
действует только на следующий код, тогда как в Oracle FM
её действие распространяется на все последующие коды, пока не будет отключено последующим модификатором FM
.
TM
не затрагивает замыкающие пробелы. Функции to_timestamp
и to_date
игнорируют указание TM
.
to_timestamp
и to_date
пропускают повторяющиеся пробелы во входной строке, если только не используется параметр FX
. Например, to_timestamp('2000 JUN', 'YYYY MON')
будет работать, но to_timestamp('2000 JUN', 'FXYYYY MON')
вернёт ошибку, так как to_timestamp
в данном случае ожидает только один разделяющий пробел. Приставка FX
должна быть первой в шаблоне.
to_timestamp
и to_date
предназначены для обработки входных форматов, для которых недостаточно простого приведения. Эти функции интерпретируют вводимые данные с послаблениями, проверяя только грубые ошибки. Хотя они выдают корректные данные, результат может отличаться от ожидаемого. В частности, входные аргументы этих функций не ограничиваются обычными диапазонами, так что to_date('20096040','YYYYMMDD')
выдаёт 2014-01-17
, а не ошибку. С приведением такого не происходит.
Шаблоны для функций to_char
могут содержать обычный текст; он будет выведен в неизменном виде. Чтобы вывести текст принудительно, например, если в нём оказываются поддерживаемые коды, его можно заключить в кавычки. Например, в строке '"Hello Year "YYYY'
, код YYYY
будет заменён номером года, а буква Y
в слове Year
останется неизменной. В функциях to_date
, to_number
и to_timestamp
при обработке подстроки в кавычках просто пропускаются символы входной строки по числу символов в подстроке, например для "XX"
будут пропущены два символа.
Если вы хотите получить в результате кавычки, перед ними нужно добавить обратную косую черту, например так: '\"YYYY Month\"'
.
Если формат года определяется менее, чем 4 цифрами, например, как YYY
, и в переданном значении года тоже меньше 4 цифр, год пересчитывается в максимально близкий к году 2020, т. е. 95
воспринимается как 1995.
С преобразованием YYYY
из строки в тип timestamp
или date
связано ограничение, когда обрабатываемый год записывается более чем 4 цифрами. После YYYY
необходимо будет добавить не цифровой символ или соответствующий код, иначе год всегда будет восприниматься как 4 цифры. Например, в to_date('200001131', 'YYYYMMDD')
(с годом 20000) год будет интерпретирован как состоящий из 4 цифр; чтобы исправить ситуацию, нужно добавить не цифровой разделитель после года, как в to_date('20000-1131', 'YYYY-MMDD')
, или код как в to_date('20000Nov31', 'YYYYMonDD')
.
В преобразованиях из строки в тип timestamp
или date
, поле CC
(век) игнорируется, если шаблон включает поля YYY
, YYYY
или Y,YYY
. Когда CC
используется с YY
или Y
, год вычисляется как год данного столетия. Если присутствует только код столетия, без года, подразумевается первый год этого века.
Даты по недельному календарю ISO 8601 (отличающиеся от григорианских) можно передать функциям to_timestamp
и to_date
одним из двух способов:
Год, номер недели и дня недели: например,
to_date('2006-42-4', 'IYYY-IW-ID')
возвращает дату2006-10-19
. Если день недели опускается, он считается равным 1 (понедельнику).Год и день года: например,
to_date('2006-291', 'IYYY-IDDD')
также возвращает2006-10-19
.
Попытка ввести дату из смеси полей григорианского и недельного календаря ISO 8601 бессмысленна, поэтому это будет считаться ошибкой. В контексте ISO 8601 понятия «номер месяца» и «день месяца» не существуют, а в григорианском календаре нет понятия номера недели по ISO.
Внимание
Тогда как to_date
не примет смесь полей григорианского и недельного календаря ISO, to_char
способна на это, так как форматы вроде YYYY-MM-DD (IYYY-IDDD)
могут быть полезны. Но избегайте форматов типа IYYY-MM-DD
; в противном случае с датами в начале года возможны сюрпризы. (За дополнительными сведениями обратитесь к Подразделу 9.9.1.)
При преобразовании из текстовой строки в timestamp
, миллисекунды (MS
) или микросекунды (US
) воспринимаются как дробная часть числа секунд. Например, to_timestamp('12:3', 'SS:MS')
— это не 3 миллисекунды, а 300, так как это значение воспринимается как 12 + 0.3 сек. Это значит, что для формата SS:MS
вводимые значения 12:3
, 12:30
и 12:300
задают одно и то же число миллисекунд. Чтобы получить три миллисекунды, время нужно записать в виде 12:003
, тогда это будет воспринято как 12 + 0.003 = 12.003 сек.
Ещё более сложный пример: to_timestamp('15:12:02.020.001230', 'Hh34:MI:SS.MS.US')
будет преобразовано в 15 часов, 12 минут и 2 секунды + 20 миллисекунд + 1230 микросекунд = 2.021230 seconds.
Нумерация дней недели в to_char(..., 'ID')
соответствует функции extract(isodow from ...)
, но нумерация to_char(..., 'D')
не соответствует нумерации, принятой в extract(dow from ...)
.
Функция to_char(interval)
обрабатывает форматы HH
и Hh22
в рамках 12 часов, то есть 0 и 36 часов будут выводиться как 12
, тогда как Hh34
выводит значение полностью и для интервалов выводимое значение может превышать 23.
postgrespro.ru
postgresql — Postgres Преобразование типов данных
Неправильный выбор для сохранения даты в качестве varchar
. Это очень хорошо, что вы хотите изменить это.
Первым шагом является преобразование столбцов с помощью оператора ALTER TABLE
:
alter table the_table
ALTER COLUMN col_1 TYPE date using col_1::date,
ALTER COLUMN col_2 TYPE date using col_2::date;
Обратите внимание, что это произойдет, если у вас есть значение в тех столбцах, которые нельзя преобразовать в правильную дату. Если вы обнаружите, что вам нужно сначала исправить эти недопустимые строки, прежде чем вы сможете изменить тип данных.
Я хочу, чтобы он продолжал оставаться в ГГГГ-ММ-DD
Это заблуждение. DATE
(или timestamp
) не имеет «формата». Как только он будет сохранен в качестве даты, вы можете отобразить его в любом формате.
Моя конечная цель — найти даты в таком формате:
2016-01-01
не является допустимым 2016-01-01
даты, может быть указана правильная (т. 2016-01-01
Правильно напечатанная) константа даты, например, с использованием date '2016-01-01'
(обратите внимание на одинарные кавычки!
Таким образом, ваш запрос будет выглядеть следующим образом:
select col_1, col_2 from table where col_1 between date '2016-01-01' AND date '2016-05-31';
Если у вас есть много таких запросов, вам следует подумать о создании индекса в столбцах даты.
Что касается формата даты:
Вы говорите мне, что, несмотря на наличие типов данных varchar, я все еще могу (прямо сейчас) искать между конкретными датами, просто набирая слово date и помещая одинарные кавычки между двумя датами
Нет, это не так. SQL является строго типизированным языком и как таковой будет сравнивать только значения одного и того же типа.
Использование литерала даты ANSI (или, например, to_date()
) приводит к константе типа (то есть к определенному типу данных).
Разница между date '2016-01-01' and '2016-01-01' is the same as between
42 (a number) and
«42» (строка).
Если вы сравниваете строку с датой, вы сравниваете яблоки и апельсины, и база данных будет делать неявное преобразование типа данных из одного типа в другое. Этого следует избегать любой ценой.
Если вы не хотите изменять таблицу, вы должны использовать запрос sagi, который явно преобразует строки в даты, а затем делает сравнение значений (реальных) (не строк)
qaru.site
postgresql — Postgres приведение bit(n) к bytea
Stack Overflow на русском- 0
- +0
- Тур Начните с этой страницы, чтобы быстро ознакомиться с сайтом
- Справка Подробные ответы на любые возможные вопросы
- Мета Обсудить принципы работы и политику сайта
- О нас Узнать больше о компании Stack Overflow
- Бизнес Узнать больше о поиске разработчиков или рекламе на сайте
- Войти Регистрация
-
текущее сообщество
- Stack Overflow на русском справка чат
ru.stackoverflow.com
ascii (строка) | int | ASCII код первого символа заданной строки. Для UTF8 возвращает код Unicode данного символа. Для других многобайтовых кодировок, аргумент должен быть ASCII символом. | ascii(‘x’) | 120 |
btrim (строка text
[, символы text]) | text | Удаляет наиболее длинную подстроку, содержащую только заданные символы (по умолчанию, пробел) из начала и конца заданной строки | btrim(‘xyxtrimyyx’, ‘xy’) | trim |
chr (int) | text | Символ с указанным кодом. Для UTF8 аргумент трактуется как код Unicode. Для других многобайтовых кодировок аргумент должен соответствовать какому-либо ASCII символу. Символ NULL (0) не разрешается, потому что текстовые типы данных не могут хранить такие символы. | chr(65) | A |
convert (строка bytea,
src_encoding name,
dest_encoding name) | bytea | Преобразует строку в кодировку, заданную аргументом dest_encoding. Исходная кодировка задаётся аргументом src_encoding. Аргумент строка должен быть в исходной кодировке. Преобразование может быть задано с помощью CREATE CONVERSION. Также есть несколько предварительно определённых преобразований. См. доступные преобразования в Table 9-7. | convert(‘text_in_utf8’, ‘UTF8’, ‘LATIN1’) | text_in_utf8, представленный в кодировке Latin-1 (ISO 8859-1) |
convert_from (строка bytea,
src_encoding name) | text | Преобразует строку в кодировку СУБД. Исходная кодировка задаётся аргументом src_encoding. Заданная строка должна быть и исходной кодировке. | convert_from(‘text_in_utf8’, ‘UTF8’) | text_in_utf8, представленный в текущей кодировке СУБД |
convert_to (строка text,
dest_encoding name) | bytea | Преобразует строку в кодировку dest_encoding. | convert_to(‘some text’, ‘UTF8’) | some text, представленный в кодировке UTF8 |
decode (строка text,
type text) | bytea | Декодирует бинарные данных из заданной строки, которые
ранее были закодированы с помощью функции encode . Тип аргумента
такой же как в функции encode . | decode(‘MTIzAAE=’, ‘base64’) | 123\000\001 |
encode (данные bytea,
тип text) | text | Кодирует бинарные данные в другое представление. Поддерживаются такие типы представлений как: base64, hex, escape. Escape просто выводит нулевые байты типа \000 и двойную обратную косую черту. | encode(E’123\\000\\001′, ‘base64’) | MTIzAAE= |
initcap (строка) | text | Преобразует первую букву каждого слова в верхний регистр и остаток слова в нижний. Слова являются алфавитно-цифровыми последовательностями, разделенными не алфавитно-цифровыми символами. | initcap(‘hi THOMAS’) | Hi Thomas |
length (строка) | int | Количество символов в заданной строке | length(‘jose’) | 4 |
length (строкаbytea,
кодировка name ) | int | Количество символов в заданной строке в указанной кодировке. Заданная строка должна быть в указанной кодировке. | length(‘jose’, ‘UTF8’) | 4 |
lpad (строка text,
длина int
[, fill text]) | text | Заполняет заданную строку до указанной длины символами, заданными параметром fill (по умолчанию, пробел). Если строка уже длиннее, чем длина, то она усекается (справа). | lpad(‘hi’, 5, ‘xy’) | xyxhi |
ltrim (строка text
[, символы text]) | text | Удаляет наиболее длинную подстроку, содержащую только заданные символы (по умолчанию, пробел) из начала заданной строки | ltrim(‘zzzytrim’, ‘xyz’) | trim |
md5 (строка) | text | Вычисляет MD5 хэш заданной строки, возвращая резульат в шестнадцетеричном виде | md5(‘abc’) | 900150983cd24fb0 d6963f7d28e17f72 |
pg_client_encoding () | name | Текущая кодировка клиента | pg_client_encoding() | SQL_ASCII |
quote_ident (строка text) | text | Возвращает заданную строку, заключённую в кавычки должным образом так, чтобы её было можно использовать как идентификатор в операторах SQL, работающих со строками. Кавычки добавляются только если они необходимы (например, если строка содержит символы недопустимые в идентификаторах без кавычек или регистро-зависмые символы). Кавычки внутри строки соответственно дублируются. См. также Example 38-1. | quote_ident(‘Foo bar’) | «Foo bar» |
quote_literal (строки text) | text | Возвращает заданную строку, заключённую в кавычки должным образом так,
чтобы тобы её было можно использовать как строковый литерал в операторах
SQL, работающих со строками. Одиночные кавычки
и символы обратная косая черта внутри строки соответствующим образом
дублируются. Обратите внимание, что функция quote_literal возвращает NULL при указании NULL в качестве параметра; если аргумент
может быть NULL, часто более подходящей будет функция quote_nullable . См. также
Example 38-1. | quote_literal(‘O\’Reilly’) | ‘O»Reilly’ |
quote_literal (значение anyelement) | text | Принудительно приводит заданное значение к текстовому типу и затем заключает его в кавычки как литерал. Одиночные кавычки и символы обратная косая черта внутри строки соответственно дублируются. | quote_literal(42.5) | ‘42.5’ |
quote_nullable (строки text) | text | Возвращает заданную строку, заключённую в кавычки должным образом так, чтобы тобы её было можно использовать как строковый литерал в операторах SQL, работающих со строками; или если аргумент является NULL, возвращает return NULL. Одиночные кавычки и символы обратная косая черта внутри строки соответственно дублируются. См. также Example 38-1. | quote_nullable(NULL) | NULL |
quote_nullable (значение anyelement) | text | Принудительно приводит указанное значение к текстовому типу и заключает его в кавычки как литерал; или если аргумент это NULL, возвращает NULL. Одиночные кавычки и символы обратная косая черта внутри строки соответственно дублируются. | quote_nullable(42.5) | ‘42.5’ |
regexp_matches (строка text, шаблон text [, flags text]) | setof text[] | Возвращает все подстроки, полученные в результате совпадения заданной строки с регулярным выражением (шаблоном) POSIX Подробности см. в Section 9.7.3. | regexp_matches(‘foobarbequebaz’, ‘(bar)(beque)’) | {bar,beque} |
regexp_replace (строка text, шаблон text, replacement text [, флаги text]) | text | Заменяет подстроки, совпавшие с регулярным выражением (шаблоном) POSIX в заданной строке. Подробности см. в Section 9.7.3. | regexp_replace(‘Thomas’, ‘.[mN]a.’, ‘M’) | ThM |
regexp_split_to_array (строка text, шаблон text [, флаги text ]) | text[] | Разбивает заданную строку, используя регулярное выражение (шаблон) POSIX как разделитель. Подробности см. в Section 9.7.3. | regexp_split_to_array(‘hello world’, E’\\s+’) | {hello,world} |
regexp_split_to_table (строка text, шаблон text [, флаги text]) | setof text | Разбивает заданную строку, используя регулярное выражение (шаблон) POSIX как разделитель. Подробности см. в Section 9.7.3. | regexp_split_to_table(‘hello world’, E’\\s+’) | hello world (2 rows) |
repeat (строка text, количество int) | text | Повторяет заданную строку заданное количество раз | repeat(‘Pg’, 4) | PgPgPgPg |
replace (строка text,
from text,
to text) | text | Заменяет все вхождения в заданной строке подстроки from на подстроку to | replace(‘abcdefabcdef’, ‘cd’, ‘XX’) | abXXefabXXef |
rpad (строка text,
длина int
[, fill text]) | text | Заполняет заданную строку на заданную длину, путём добавления символов, заданных в fill (по умолчанию, пробел). Если заданная строка уже длиннее, чем заданная длина, то она будет усечена. | rpad(‘hi’, 5, ‘xy’) | hixyx |
rtrim (строка text
[, символы text]) | text | Удаляет наиболее длинную подстроку, содержащую заданные символы (по умолчанию, пробел) из конца заданной строки | rtrim(‘trimxxxx’, ‘x’) | trim |
split_part (строка text,
разделитель text,
поле int) | text | Разбивает заданную строку, используя заданный разделитель и возвращает указанное поле (нумерация начинается с единицы) | split_part(‘abc~@~def~@~ghi’, ‘~@~’, 2) | def |
strpos (строка, подстрока) | int | Положение заданной подстроки (тоже самое, что и функция position(подстрока in строка), но обратите внимание на обратный порядок аргументов) | strpos(‘high’, ‘ig’) | 2 |
substr (строка, from [, count]) | text | Извлекает подстроку (также как функция substring(строка from from for count)) | substr(‘alphabet’, 3, 2) | ph |
to_ascii (строка text
[, кодировка text]) | text | Преобразует заданную строку в ASCII из другой кодировки (поддерживаются только преобразования из кодировок LATIN1, LATIN2, LATIN9 и WIN1250) | to_ascii(‘Karel’) | Karel |
to_hex (число int
or bigint) | text | Преобразует заданное число в его шестнадцетеричный эквивалент | to_hex(2147483647) | 7fffffff |
translate (строка text,
from text,
to text) | text | Любой символ из заданной строки, который совпадает с каким-либо символом в наборе символов from, заменяется на соответствующий символ в наборе символов to. | translate(‘12345′, ’14’, ‘ax’) | a23x5 |
postgresql.ru.net
Postgres Pro Standard : Документация: 11: 10.1. Обзор : Компания Postgres Professional
SQL — язык со строгой типизацией. То есть каждый элемент данных в нём имеет некоторый тип, определяющий его поведение и допустимое использование. Postgres Pro наделён расширяемой системой типов, более универсальной и гибкой по сравнению с другими реализациями SQL. При этом преобразования типов в Postgres Pro в основном подчиняются определённым общим правилам, для их понимания не нужен эвристический анализ. Благодаря этому в выражениях со смешанными типами можно использовать даже типы, определённые пользователями.
Анализатор выражений Postgres Pro разделяет их лексические элементы на пять основных категорий: целые числа, другие числовые значения, текстовые строки, идентификаторы и ключевые слова. Константы большинства не числовых типов сначала классифицируются как строки. В определении языка SQL допускается указывать имена типов в строках и это можно использовать в Postgres Pro, чтобы направить анализатор по верному пути. Например, запрос:
SELECT text 'Origin' AS "label", point '(0,0)' AS "value"; label | value --------+------- Origin | (0,0) (1 row)
содержит две строковых константы, типа text
и типа point
. Если для такой константы не указан тип, для неё первоначально предполагается тип unknown
, который затем может быть уточнён, как описано ниже.
В SQL есть четыре фундаментальных фактора, определяющих правила преобразования типов для анализатора выражений Postgres Pro:
- Вызовы функций
Система типов Postgres Pro во многом построена как дополнение к богатым возможностям функций. Функции могут иметь один или несколько аргументов, и при этом Postgres Pro разрешает перегружать имена функций, так что имя функции само по себе не идентифицирует вызываемую функцию; анализатор выбирает правильную функцию в зависимости от типов переданных аргументов.
- Операторы
Postgres Pro позволяет использовать в выражениях префиксные и постфиксные операторы с одним аргументом, а также операторы с двумя аргументами. Как и функции, операторы можно перегружать, так что и с ними существует проблема выбора правильного оператора.
- Сохранение значений
SQL-операторы
INSERT
иUPDATE
помещают результаты выражений в таблицы. При этом получаемые значения должны соответствовать типам целевых столбцов или, возможно, приводиться к ним.UNION
,CASE
и связанные конструкцииТак как все результаты запроса объединяющего оператора
SELECT
должны оказаться в одном наборе столбцов, результаты каждого подзапросаSELECT
должны приводиться к одному набору типов. Подобным образом, результирующие выражения конструкцииCASE
должны приводиться к общему типу, так как выражениеCASE
в целом должно иметь определённый выходной тип. То же справедливо в отношении конструкцийARRAY
и функцийGREATEST
иLEAST
.
Информация о существующих преобразованиях или приведениях типов, для каких типов они определены и как их выполнять, хранится в системных каталогах. Пользователь также может добавить дополнительные преобразования с помощью команды CREATE CAST. (Обычно это делается, когда определяются новые типы данных. Набор приведений для встроенных типов достаточно хорошо проработан, так что его лучше не менять.)
Дополнительная логика анализа помогает выбрать оптимальное приведение в группах типов, допускающих неявные преобразования. Для этого типы данных разделяются на несколько базовых категорий, которые включают: boolean
, numeric
, string
, bitstring
, datetime
, timespan
, geometric
, network
и пользовательские типы. (Полный список категорий приведён в Таблице 51.63; хотя его тоже можно расширить, определив свои категории.) В каждой категории могут быть выбраны один или несколько предпочитаемых типов, которые будут считаться наиболее подходящими при рассмотрении нескольких вариантов. Аккуратно выбирая предпочитаемые типы и допустимые неявные преобразования, можно добиться того, что выражения с неоднозначностями (в которых возможны разные решения задачи преобразования) будут разрешаться наилучшим образом.
Все правила преобразования типов разработаны с учётом следующих принципов:
Результат неявных преобразованиях всегда должен быть предсказуемым и понятным.
Если в неявном преобразовании нет нужды, анализатор и исполнитель запроса не должны тратить лишнее время на это. То есть, если запрос хорошо сформулирован и типы значений совпадают, он должен выполняться без дополнительной обработки в анализаторе и без лишних вызовов неявных преобразований.
Кроме того, если запрос изначально требовал неявного преобразования для функции, а пользователь определил новую функцию с точно совпадающими типами аргументов, анализатор должен переключиться на новую функцию и больше не выполнять преобразование для вызова старой.
postgrespro.ru