CREATE TYPE#

CREATE TYPE

CREATE TYPE

CREATE TYPE — определить новый тип данных

Синтаксис

CREATE TYPE name AS
    ( [ attribute_name data_type [ COLLATE collation ] [, ... ] ] )

CREATE TYPE name AS ENUM
    ( [ 'label' [, ... ] ] )

CREATE TYPE name AS RANGE (
    SUBTYPE = subtype
    [ , SUBTYPE_OPCLASS = subtype_operator_class ]
    [ , COLLATION = collation ]
    [ , CANONICAL = canonical_function ]
    [ , SUBTYPE_DIFF = subtype_diff_function ]
    [ , MULTIRANGE_TYPE_NAME = multirange_type_name ]
)

CREATE TYPE name (
    INPUT = input_function,
    OUTPUT = output_function
    [ , RECEIVE = receive_function ]
    [ , SEND = send_function ]
    [ , TYPMOD_IN = type_modifier_input_function ]
    [ , TYPMOD_OUT = type_modifier_output_function ]
    [ , ANALYZE = analyze_function ]
    [ , SUBSCRIPT = subscript_function ]
    [ , INTERNALLENGTH = { internallength | VARIABLE } ]
    [ , PASSEDBYVALUE ]
    [ , ALIGNMENT = alignment ]
    [ , STORAGE = storage ]
    [ , LIKE = like_type ]
    [ , CATEGORY = category ]
    [ , PREFERRED = preferred ]
    [ , DEFAULT = default ]
    [ , ELEMENT = element ]
    [ , DELIMITER = delimiter ]
    [ , COLLATABLE = collatable ]
)

CREATE TYPE name

Описание

CREATE TYPE регистрирует новый тип данных для использования в текущей базе данных. Пользователь, который определяет тип, становится его владельцем.

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

Существует пять форм команды CREATE TYPE, как показано в синтаксическом обзоре выше. Они соответственно создают композитный тип, перечислимый тип, диапазонный тип, базовый тип или заглушечный тип. Первые четыре из них рассматриваются далее по порядку. Заглушечный тип просто является заполнителем для типа, который будет определен позже; он создается путем выполнения команды CREATE TYPE без параметров, кроме имени типа. Заглушечные типы необходимы в качестве предварительных ссылок при создании диапазонных типов и базовых типов, как описано в соответствующих разделах.

Составные типы

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

Для возможности создания составного типа необходимо иметь привилегию USAGE на всех типах атрибутов.

Перечисляемые типы

Вторая форма команды CREATE TYPE создает перечислимый (enum) тип, как описано в Раздел 8.7. Перечислимые типы принимают список заключенных в кавычки меток, каждая из которых должна быть короче NAMEDATALEN байт (64 байта в стандартной сборке Tantor BE). (Возможно создание перечислимого типа с нулевым количеством меток, но такой тип не может использоваться для хранения значений до добавления хотя бы одной метки с помощью ALTER TYPE).

Типы диапазонов

Третья форма CREATE TYPE создает новый тип диапазона, как описано в Раздел 8.17.

Тип диапазона может иметь любой subtype с ассоциированным классом операторов b-tree (для определения порядка значений для типа диапазона). Обычно для определения порядка используется класс операторов b-tree по умолчанию подтипа; для использования нестандартного класса операторов следует указать его имя с помощью параметра subtype_opclass. Если подтип является сравнимым, и нужно использовать нестандартное правило сортировки в порядке диапазона, укажите желаемое правило сортировки с помощью параметра collation.

Необязательная функция canonical должна принимать один аргумент типа диапазон, который определяется, и возвращать значение того же типа. Она используется для преобразования значений диапазона в каноническую форму, когда это применимо. См. Раздел 8.17.8 для получения дополнительной информации. Создание функции canonical немного сложно, поскольку она должна быть определена до объявления типа диапазона. Для этого сначала необходимо создать пустой тип, который является типом-заглушкой и не имеет свойств, кроме имени и владельца. Это делается с помощью команды CREATE TYPE name, без дополнительных параметров. Затем функцию можно объявить, используя тип-заглушку в качестве аргумента и результата, и, наконец, тип диапазона можно объявить с использованием того же имени. Это автоматически заменяет запись типа-заглушки на допустимый тип диапазона.

Необязательная функция subtype_diff должна принимать два значения типа subtype в качестве аргумента, и возвращать значение типа double precision, представляющее разницу между двумя заданными значениями. Хотя это необязательно, предоставление этой функции позволяет значительно повысить эффективность индексов GiST на столбцах типа диапазон. См. Раздел 8.17.8 для получения дополнительной информации.

Опциональный параметр multirange_type_name указывает имя соответствующего мультидиапазонного типа. Если не указано, это имя выбирается автоматически следующим образом. Если имя диапазонного типа содержит подстроку range, то имя мультидиапазонного типа формируется путем замены подстроки range на multirange в имени диапазонного типа. В противном случае, имя мультидиапазонного типа формируется путем добавления суффикса _multirange к имени диапазонного типа.

Базовые типы

Четвертая форма команды CREATE TYPE создает новый базовый тип (скалярный тип). Для создания нового базового типа вы должны быть суперпользователем. (Это ограничение сделано, потому что неправильное определение типа может запутать или даже вызвать сбой сервера).

Все параметры можно указать в любом порядке, не только таком, как показано выше, и большинство из них являются необязательными. Вы должны зарегистрировать две или более функции (с помощью CREATE FUNCTION) перед определением типа. Поддерживающие функции input_function и output_function обязательны, в то время как функции receive_function, send_function, type_modifier_input_function, type_modifier_output_function, analyze_function и subscript_function являются необязательными. Обычно эти функции должны быть написаны на языке C или другом низкоуровневом языке.

Функция input_function преобразует внешнее текстовое представление типа во внутреннее представление, используемое операторами и функциями, определенными для этого типа. Функция output_function выполняет обратное преобразование. Входная функция может быть объявлена как принимающая один аргумент типа cstring, или как принимающая три аргумента типов cstring, oid, integer. Первый аргумент - это входной текст в виде C-строки, второй аргумент - собственный OID типа (за исключением массивных типов, которые вместо этого получают OID их элементного типа), а третий - typmod целевой колонки, если он известен (-1 будет передан, если неизвестен). Входная функция должна возвращать значение самого типа данных. Обычно входная функция должна быть объявлена как STRICT; если это не так, она будет вызвана с NULL в качестве первого параметра при чтении NULL входного значения. В этом случае функция все равно должна вернуть NULL, если только она не вызывает ошибку. (Этот случай в основном предназначен для поддержки входных функций доменов, которые могут потребовать отклонения NULL-входов). Выходная функция должна быть объявлена как принимающая один аргумент нового типа данных. Выходная функция должна возвращать тип cstring. Выходные функции не вызываются для значений NULL.

Необязательная функция receive_function преобразует внешнее двоичное представление типа во внутреннее представление. Если эта функция не предоставляется, тип не может участвовать в двоичном вводе. Двоичное представление должно быть выбрано таким образом, чтобы его преобразование во внутреннюю форму было дешевым, при этом оно должно быть достаточно переносимым. (Например, стандартные целочисленные типы данных используют сетевой порядок байтов в качестве внешнего двоичного представления, а внутреннее представление - в порядке байтов машинного устройства). Функция приема должна выполнять достаточную проверку, чтобы убедиться, что значение допустимо. Функцию приема можно объявить как принимающую один аргумент типа internal, или как принимающую три аргумента типов internal, oid, integer. Первый аргумент - указатель на буфер StringInfo, содержащий принятую байтовую строку; необязательные аргументы такие же, как для функции ввода текста. Функция приема должна возвращать значение самого типа данных. Обычно функцию приема следует объявить как STRICT; если это не так, она будет вызвана с NULL в качестве первого параметра при чтении NULL входного значения. В этом случае функция должна все равно вернуть NULL, если она не вызывает ошибку. (Этот случай в основном предназначен для поддержки функций приема домена, которые могут потребоваться для отклонения NULL-входов). Аналогично, необязательная функция send_function преобразует из внутреннего представления во внешнее двоичное представление. Если эта функция не предоставляется, тип не может участвовать в двоичном выводе. Функция отправки должна быть объявлена как принимающая один аргумент нового типа данных. Функция отправки должна возвращать тип bytea. Функции отправки не вызываются для значений NULL.

На этом этапе вы, вероятно, задаетесь вопросом, как могут быть объявлены функции ввода и вывода с результатами или аргументами нового типа, когда они должны быть созданы до создания нового типа. Ответ в том, что тип должен сначала быть определен как "заглушка" (shell type), которая является типом-заменителем и не имеет свойств, кроме имени и владельца. Это делается с помощью команды CREATE TYPE name без дополнительных параметров. Затем функции ввода-вывода на языке C могут быть определены с ссылкой на тип-заглушку. Наконец, команда CREATE TYPE с полным определением заменяет заглушку полным и действительным определением типа, после чего новый тип может быть использован нормально.

Необходимы необязательные функции type_modifier_input_function и type_modifier_output_function, если тип поддерживает модификаторы, то есть необязательные ограничения, присоединенные к объявлению типа, такие как char(5) или numeric(30,2). Tantor BE позволяет определять пользовательские типы с одной или несколькими простыми константами или идентификаторами в качестве модификаторов. Однако эта информация должна быть упакована в одно неотрицательное целое число для хранения в системных каталогах. Функция type_modifier_input_function получает объявленные модификаторы в виде массива cstring. Она должна проверить значения на допустимость (выдавая ошибку, если они неверны), и если они правильные, вернуть одно неотрицательное целое значение integer, которое будет сохранено в столбце typmod. Модификаторы типа будут отклонены, если у типа нет функции type_modifier_input_function. Функция type_modifier_output_function преобразует внутреннее целочисленное значение typmod обратно в правильную форму для отображения пользователю. Она должна вернуть значение cstring, которое является точной строкой для добавления к имени типа; например, функция для типа numeric может вернуть (30,2). Допускается опускать функцию type_modifier_output_function, в этом случае формат отображения по умолчанию будет просто храниться целочисленное значение typmod, заключенное в скобки.

Необязательная функция analyze_function выполняет сбор статистики для столбцов с определенным типом данных. По умолчанию ANALYZE пытается собрать статистику, используя операторы equals и less-than для типа данных, если для него существует класс операторов b-tree по умолчанию. Для нескалярных типов данных это поведение, скорее всего, не подходит, поэтому его можно изменить, указав пользовательскую функцию анализа. Функция анализа должна быть объявлена с одним аргументом типа internal и возвращать результат типа boolean. Подробное описание API для функций анализа приведено в файле src/include/commands/vacuum.h.

Необязательный параметр subscript_function позволяет тип данных быть подписанным в SQL-командах. Указание этой функции не приводит к тому, что тип считается массивным типом true; например, он не будет кандидатом для типа результата конструкций ARRAY[]. Но если подписывание значения типа является естественной нотацией для извлечения данных из него, то subscript_function может быть написана для определения того, что это означает. Функция подписывания должна быть объявлена с одним аргументом типа internal и возвращать результат типа internal, который является указателем на структуру методов (функций), реализующих подписывание. Подробное API для функций подписывания приведено в файле src/include/nodes/subscripting.h. Также может быть полезно ознакоммиться с реализацией массива в файле src/backend/utils/adt/arraysubs.c или более простым кодом в файле contrib/hstore/hstore_subs.c. Дополнительная информация приведена ниже в разделе Array Types.

В то время как детали внутреннего представления нового типа известны только функциям ввода-вывода и другим функциям, которые вы создаете для работы с типом, есть несколько свойств внутреннего представления, которые должны быть объявлены в Tantor BE. Прежде всего, это internallength. Базовые типы данных могут быть фиксированной длины, в этом случае internallength является положительным целым числом, или переменной длины, что указывается установкой internallength в VARIABLE. (Внутренне это представлено установкой typlen в -1). Внутреннее представление всех типов переменной длины должно начинаться с 4-байтового целого числа, указывающего общую длину этого значения типа. (Обратите внимание, что поле длины часто кодируется, как описано в Раздел 70.2; небезопасно обращаться к нему напрямую).

Необязательный флаг PASSEDBYVALUE указывает, что значения этого типа данных передаются по значению, а не по ссылке. Типы, передаваемые по значению, должны иметь фиксированную длину, и их внутреннее представление не может быть больше размера типа Datum (4 байта на некоторых машинах, 8 байт на других).

Параметр alignment определяет требуемое выравнивание для хранения типа данных. Разрешенные значения соответствуют выравниванию на границах 1, 2, 4 или 8 байт. Обратите внимание, что переменные типы должны иметь выравнивание не менее 4, так как они обязательно содержат int4 в качестве своего первого компонента.

Параметр storage позволяет выбрать стратегии хранения для переменной длины данных. (Только для фиксированной длины разрешено использование plain). plain указывает, что данные данного типа всегда будут храниться встроенными и не сжатыми. extended указывает, что система сначала попытается сжать длинное значение данных, и если оно все еще слишком длинное, переместит его из основной строки таблицы. external позволяет переместить значение из основной таблицы, но система не будет пытаться сжать его. main позволяет сжатие, но не рекомендует перемещение значения из основной таблицы. (Элементы данных с этой стратегией хранения могут быть перемещены из основной таблицы, если нет другого способа поместить строку, но они будут предпочтительно храниться в основной таблице по сравнению с элементами extended и external).

Все значения storage, кроме plain, подразумевают, что функции типа данных могут обрабатывать значения, которые были toasted, как описано в Раздел 70.2 и Раздел 35.12.1. Конкретное другое значение просто определяет стратегию хранения TOAST по умолчанию для столбцов типа данных, подлежащих TOAST; пользователи могут выбирать другие стратегии для отдельных столбцов с помощью ALTER TABLE SET STORAGE.

Параметр like_type предоставляет альтернативный метод для указания основных свойств представления типа данных: копирование их из существующего типа. Значения internallength, passedbyvalue, alignment и storage копируются из указанного типа. (Возможно, хотя обычно нежелательно, переопределить некоторые из этих значений, указав их вместе с предложением LIKE). Указание представления таким образом особенно полезно, когда низкоуровневая реализация нового типа piggybacks на существующем типе каким-либо образом.

Параметры category и preferred могут быть использованы для управления неоднозначными ситуациями, в которых применяется неявное преобразование типов. Каждый тип данных принадлежит категории, названной одним символом ASCII, и каждый тип либо предпочтительный, либо не является таковым в своей категории. Парсер будет предпочитать преобразование к предпочтительным типам (но только из других типов в той же категории), когда это правило помогает разрешить перегруженные функции или операторы. Дополнительные сведения см. в разделе Глава 10. Для типов, которые не имеют неявных преобразований к или из других типов, достаточно оставить эти настройки по умолчанию. Однако для группы связанных типов, имеющих неявные преобразования, часто полезно отметить их все как принадлежащие категории и выбрать один или два наиболее общих типа как предпочтительные внутри категории. Параметр category особенно полезен при добавлении пользовательского типа к существующей встроенной категории, такой как числовые или строковые типы. Однако также возможно создание новых полностью пользовательских категорий типов. Выберите любой символ ASCII, отличный от заглавной буквы, чтобы назвать такую категорию.

Можно указать значение по умолчанию, если пользователь хочет, чтобы столбцы типа данных имели значение по умолчанию, отличное от значения null. Укажите значение по умолчанию с помощью ключевого слова DEFAULT. (Такое значение по умолчанию может быть переопределено явным предложением DEFAULT, присоединенным к определенному столбцу).

Для указания того, что тип является типом фиксированной длины массива, укажите тип элементов массива, используя ключевое слово ELEMENT. Например, для определения массива 4-байтовых целых чисел (int4) укажите ELEMENT = int4. Дополнительные сведения см. в разделе Array Types ниже.

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

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

Типы массивов

Всякий раз, когда создается пользовательский тип, Tantor BE автоматически создает соответствующий массивный тип, имя которого состоит из типа элемента, предшествующего подчеркиванию, и обрезается, если необходимо, чтобы оно было меньше NAMEDATALEN байтов в длину. (Если сгенерированное имя сталкивается с существующим именем типа, процесс повторяется, пока не будет найдено имя, не сталкивающееся). Этот неявно созданный массивный тип имеет переменную длину и использует встроенные функции ввода и вывода array_in и array_out. Кроме того, этот тип используется системой для конструкций, таких как ARRAY[] для пользовательского типа. Массивный тип отслеживает любые изменения владельца или схемы его элементного типа и удаляется, если элементный тип удаляется.

Вы можете справедливо спросить, зачем существует опция ELEMENT, если система автоматически создает правильный тип массива. Основной случай, когда полезно использовать опцию ELEMENT, это когда вы создаете тип фиксированной длины, который внутренне является массивом из нескольких идентичных элементов, и нужно позволить доступ к этим элементам напрямую по индексу, в дополнение к любым операциям, которые вы планируете предоставить для всего типа. Например, тип point представлен всего двумя числами с плавающей запятой, к которым можно получить доступ с помощью point[0] и point[1]. Обратите внимание, что эта возможность работает только для типов фиксированной длины, внутренняя форма которых представляет собой последовательность идентичных полей фиксированной длины. По историческим причинам (то есть это явно неправильно, но слишком поздно, чтобы это изменить), индексация типов массивов фиксированной длины начинается с нуля, а не с единицы, как для массивов переменной длины.

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

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

Параметры

name

Имя (опционально с указанием схемы) создаваемого типа.

attribute_name

Имя атрибута (столбца) для составного типа.

data_type

Имя существующего типа данных, которое станет столбцом составного типа.

collation

Имя существующей сортировки, которая будет связана с колонкой составного типа или с типом диапазона.

label

Строковый литерал, представляющий текстовую метку, связанную с одним значением типа enum.

subtype

Имя типа элемента, который будет представлять диапазоны.

subtype_operator_class

Имя класса оператора b-tree для подтипа.

canonical_function

Имя функции канонизации для типа диапазона.

subtype_diff_function

Имя функции различия для подтипа.

multirange_type_name

Имя соответствующего множественного типа диапазона.

input_function

Имя функции, которая преобразует данные из внешней текстовой формы типа в его внутреннюю форму.

output_function

Имя функции, которая преобразует данные из внутренней формы типа в его внешнюю текстовую форму.

receive_function

Имя функции, которая преобразует данные из внешнего двоичного формата типа в его внутреннюю форму.

send_function

Имя функции, которая преобразует данные из внутренней формы типа в его внешнюю двоичную форму.

type_modifier_input_function

Имя функции, которая преобразует массив модификаторов для типа во внутреннюю форму.

type_modifier_output_function

Имя функции, которая преобразует внутреннюю форму модификатора(-ов) типа во внешнюю текстовую форму.

analyze_function

Имя функции, выполняющей статистический анализ для типа данных.

subscript_function

Имя функции, которая определяет, что делает индексация значения типа данных.

internallength

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

alignment

Требование к выравниванию хранения типа данных. Если указано, оно должно быть char, int2, int4 или double; по умолчанию используется int4.

storage

Стратегия хранения для данного типа данных. Если указано, должно быть plain, external, extended или main; по умолчанию используется plain.

like_type

Имя существующего типа данных, у которого новый тип будет иметь такое же представление. Значения internallength, passedbyvalue, alignment и storage копируются из этого типа, если они не переопределены явным образом в другом месте в команде CREATE TYPE.

category

Код категории (один символ ASCII) для этого типа. По умолчанию используется 'U' для пользовательского типа. Другие стандартные коды категорий можно найти в Таблица 50.65. Также можно выбрать другие символы ASCII для создания пользовательских категорий.

preferred

True, если этот тип является предпочтительным типом в своей категории типов, в противном случае false. По умолчанию значение равно false. Будьте очень осторожны при создании нового предпочтительного типа в существующей категории типов, так как это может вызвать неожиданные изменения в поведении.

default

Значение по умолчанию для данного типа данных. Если оно не указано, то по умолчанию используется значение null.

element

Создаваемый тип является массивом; это указывает тип элементов массива.

delimiter

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

collatable

True, если операции этого типа могут использовать информацию о правиле сортировки. По умолчанию значение false.

Примечания

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

До версии PostgreSQL 8.3 имя сгенерированного массивного типа всегда точно соответствовало имени элементного типа с добавлением одного символа подчеркивания (_) в начале. (Имена типов были ограничены в длине на один символ меньше, чем другие имена.) Хотя это обычно все еще так, имя массивного типа может отличаться от этого в случае максимальной длины имен или коллизий с именами пользовательских типов, начинающихся с подчеркивания. Написание кода, который зависит от этой конвенции, является устаревшим. Вместо этого используйте pg_type.typarray для поиска массивного типа, связанного с данным типом.

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

Перед версией PostgreSQL 8.2 не существовал синтаксис создания типа shell-type CREATE TYPE name. Способ создания нового базового типа заключался в создании его функции ввода. В этом подходе PostgreSQL сначала видит имя нового типа данных как тип возвращаемого значения функции ввода. В этой ситуации shell-тип создается неявно, а затем он может быть использован в определениях остальных функций ввода/вывода. Этот подход все еще работает, но считается устаревшим и может быть запрещен в некоторых будущих версиях. Кроме того, чтобы избежать случайного загромождения каталогов shell-типами в результате простых опечаток в определениях функций, shell-тип будет создан только в том случае, если функция ввода написана на языке C.

В версиях Tantor BE 16 и позже, желательно, чтобы функции ввода базовых типов возвращали мягкие ошибки, используя новый механизм errsave()/ereturn(), вместо выбрасывания исключений ereport(), как в предыдущих версиях. См. src/backend/utils/fmgr/README для получения дополнительной информации.

Примеры

Этот пример создает составной тип и использует его в определении функции:

CREATE TYPE compfoo AS (f1 int, f2 text);

CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS $$
    SELECT fooid, fooname FROM foo
$$ LANGUAGE SQL;

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

CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed');

CREATE TABLE bug (
    id serial,
    description text,
    status bug_status
);

Этот пример создает тип диапазона:

CREATE TYPE float8_range AS RANGE (subtype = float8, subtype_diff = float8mi);

Этот пример создает базовый тип данных box и затем использует тип в определении таблицы:

CREATE TYPE box;

CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ;
CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ;

CREATE TYPE box (
    INTERNALLENGTH = 16,
    INPUT = my_box_in_function,
    OUTPUT = my_box_out_function
);

CREATE TABLE myboxes (
    id integer,
    description box
);

Если внутренняя структура box была бы массивом из четырех элементов типа float4, мы могли бы вместо этого использовать:

CREATE TYPE box (
    INTERNALLENGTH = 16,
    INPUT = my_box_in_function,
    OUTPUT = my_box_out_function,
    ELEMENT = float4
);

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

Этот пример создает тип большого объекта и использует его в определении таблицы:

CREATE TYPE bigobj (
    INPUT = lo_filein, OUTPUT = lo_fileout,
    INTERNALLENGTH = VARIABLE
);
CREATE TABLE big_objs (
    id integer,
    obj bigobj
);

Больше примеров, включая подходящие функции ввода и вывода, можно найти в Раздел 35.12.

Совместимость

Первая форма команды CREATE TYPE, которая создает составной тип, соответствует стандарту SQL. Другие формы являются расширениями Tantor BE. Команда CREATE TYPE в стандарте SQL также определяет другие формы, которые не реализованы в Tantor BE.

Возможность создания составного типа с нулевыми атрибутами является специфичным отклонением от стандарта Tantor BE (аналогично случаю с CREATE TABLE).