CREATE TYPE
CREATE TYPE — определить новый тип данных
Синтаксис
CREATE TYPE имя AS
( [ имя_атрибута тип_данных [ COLLATE правило_сортировки ] [, ... ] ] )
CREATE TYPE имя AS ENUM
( [ 'метка' [, ... ] ] )
CREATE TYPE имя AS RANGE (
SUBTYPE = подтип
[ , SUBTYPE_OPCLASS = класс_операторов_подтипа ]
[ , COLLATION = правило_сортировки ]
[ , CANONICAL = каноническая_функция ]
[ , SUBTYPE_DIFF = функция_разницы_подтипа ]
[ , MULTIRANGE_TYPE_NAME = имя_мультидиапазонного_типа ]
)
CREATE TYPE имя (
INPUT = функция_ввода,
OUTPUT = функция_вывода
[ , RECEIVE = функция_получения ]
[ , SEND = функция_отправки ]
[ , TYPMOD_IN = функция_ввода_модификатора_типа ]
[ , TYPMOD_OUT = функция_вывода_модификатора_типа ]
[ , ANALYZE = функция_анализа ]
[ , SUBSCRIPT = функция_обращения_по_индексу ]
[ , INTERNALLENGTH = { внутренняя_длина | VARIABLE } ]
[ , PASSEDBYVALUE ]
[ , ALIGNMENT = выравнивание ]
[ , STORAGE = хранение ]
[ , LIKE = тип_образец ]
[ , CATEGORY = категория ]
[ , PREFERRED = предпочитаемый ]
[ , DEFAULT = по_умолчанию ]
[ , ELEMENT = элемент ]
[ , DELIMITER = разделитель ]
[ , COLLATABLE = сортируемый ]
)
CREATE TYPE имя
Описание
Команда CREATE TYPE
регистрирует новый тип данных для использования в текущей
базе данных. Пользователь, определивший тип, становится его владельцем.
Если задано имя схемы, то тип будет создан в указанной схеме, в противном случае — в текущей. Имя типа должно отличаться от имени любого существующего типа или домена в той же схеме. (Поскольку таблицы связаны с типами данных, имя типа также должно отличаться от имени любой существующей таблицы в той же схеме.)
Существует пять форм команды CREATE TYPE
, как показано выше в блоке синтаксиса.
Они создают соответственно: составной тип, перечислимый тип, диапазонный тип,
базовый тип или тип-оболочку. Первые четыре из них рассматриваются ниже.
Тип-оболочка представляет собой просто заготовку для типа, который будет определен
позже; он создается командой CREATE TYPE
без параметров, только с указанием
имени типа. Типы-оболочки необходимы в качестве прямых ссылок при создании
диапазонных и базовых типов, как описывается в соответствующих разделах.
Составные типы
Первая форма CREATE TYPE
создает составной тип. Составной тип задается списком
имен атрибутов и типов данных. Для атрибута может быть также указано правило
сортировки, если тип данных является сортируемым. Составной тип по существу
совпадает с типом строки таблицы, но использование CREATE TYPE
позволяет избежать
необходимости создавать настоящую таблицу, когда требуется всего лишь определить
тип. Отдельный составной тип может быть полезен, например, в качестве аргумента
или возвращаемого типа функции.
Чтобы создать составной тип, необходимо иметь право USAGE для всех типов его атрибутов.
Перечислимые типы
Вторая форма CREATE TYPE
создает перечислимый тип, описываемый в разделе
Перечислимые типы. Перечислимые типы принимают список заключенных в кавычки меток,
каждая из которых может иметь длину не больше NAMEDATALEN байт (64 байта в
стандартной сборке QHB). (Можно создать перечислимый тип без
меток, но такой тип нельзя использовать для хранения значений, пока хотя бы одна
метка не будет добавлена с помощью команды ALTER TYPE
.)
Диапазонные типы
Третья форма CREATE TYPE
создает новый диапазонный тип, описываемый в разделе
Диапазонные типы.
подтип диапазонного типа может быть любым типом со связанным классом операторов B-дерева (для определения порядка значений в диапазонном типе). Обычно для определения порядка используется класс операторов B-дерева по умолчанию для данного подтипа; чтобы изменить класс операторов, укажите его имя в параметре класс_операторов_подтипа. Если подтип является сортируемым и вы хотите использовать правило сортировки, отличное от заданного по умолчанию, укажите желаемое правило сортировки в параметре правило_сортировки.
Необязательная каноническая_функция должна принимать один аргумент
определяемого диапазонного типа и возвращать значение того же типа. Это
используется для преобразования значений диапазона в каноническую форму, когда это
применимо. Дополнительную информацию см. в подразделе Определение новых диапазонных типов.
Создание канонической_функции немного сложнее, так как она должна быть
определена до того, как можно будет объявить диапазонный тип. Для этого необходимо
сначала создать тип-оболочку, который является заглушкой, не имеющей никаких
свойств, кроме имени и владельца. Это делается путем выполнения команды
CREATE TYPE имя
без дополнительных параметров. Затем можно объявить функцию с
типом-оболочкой в качестве аргумента и результата, и, наконец, можно объявить
диапазонный тип с тем же именем. Это автоматически заменяет тип-оболочку на
допустимый диапазонный тип.
Необязательная функция_разницы_подтипа должна принимать в качестве аргументов два значения типа подтип и возвращать значение double precision, представляющее собой разницу между двумя заданными значениями. Хотя эта функция необязательная, с ее помощью можно кардинально увеличить эффективность индексов GiST для столбцов диапазонного типа. Дополнительную информацию см. в подразделе Определение новых диапазонных типов.
Необязательный параметр имя_мультидиапазонного_типа задает имя соответствующего мультидиапазонного типа. Если этот параметр не указывается, данное имя выбирается автоматически следующим образом. Если имя диапазонного типа содержит подстроку range, то имя мультидиапазонного типа формируется путем замены в имени диапазонного типа подстроки range на подстроку multirange. В противном случае имя мультидиапазонного типа формируется путем добавления к имени диапазонного типа суффикса _multirange.
Базовые типы
Четвертая форма CREATE TYPE
создает новый базовый тип (скалярный тип). Чтобы
создать новый базовый тип, нужно быть суперпользователем. (Это ограничение сделано
потому, что ошибочное определение типа может вызвать нарушения или даже сбой в
работе сервера.)
Параметры могут перечисляться в любом порядке, а не только в том, который показан
выше, и большинство из них являются необязательными. Перед определением типа
необходимо зарегистрировать две или более функций (с помощью CREATE FUNCTION
).
Обязательными вспомогательными функциями являются функция_ввода и
функция_вывода, тогда как функции функция_получения,
функция_отправки, функция_ввода_модификатора_типа,
функция_вывода_модификатора_типа и функция_анализа можно не
указывать. Как правило, эти функции должны быть написаны на C/RUST или другом
низкоуровневом языке.
функция_ввода преобразует внешнее текстовое представление типа во внутреннее, используемое операторами и функциями, определенными для данного типа. функция_вывода выполняет обратное преобразование. Функцию ввода можно объявить как принимающую один аргумент типа cstring или как принимающую три аргумента с типами cstring, oid, integer. Первый аргумент — это вводимый текст в виде строки в стиле C/RUST, второй аргумент — собственный OID типа (за исключением типов массивов, для которых передается OID типа элемента), а третий — это typmod для целевого столбца, если он известен (и -1, если нет). Функция ввода должна возвращать значение самого типа данных. Обычно функция ввода должна объявляться как строгая (STRICT); если это не так, то при получении на вход значения NULL она будет вызываться с первым параметром NULL. В этом случае функция все равно должна возвращать NULL, иначе возникнет ошибка. (Этот случай в основном предназначен для поддержки функций ввода доменных типов, которым может понадобиться отклонять входные данные NULL.) Функция вывода должна объявляться как принимающая один аргумент нового типа данных, а возвращать должна тип cstring. Функции вывода не вызываются для значений NULL.
Необязательная функция_получения преобразует внешнее двоичное представление типа во внутреннее представление. Если эта функция не указана, тип не может участвовать в двоичном вводе. Двоичное представление должно быть выбрано так, чтобы оно легко преобразовывалось во внутреннюю форму, будучи при этом достаточно переносимым. (Например, для стандартных целочисленных типов данных в качестве внешнего двоичного представления используют сетевой порядок байтов, в то время как внутреннее представление определяется порядком байтов в процессоре.) Функция получения должна выполнять адекватную проверку на допустимость значения. Функцию получения можно объявить как принимающую один аргумент типа internal либо как принимающую три аргумента с типами internal, oid, integer. Первый аргумент — это указатель на буфер StringInfo, содержащий полученную байтовую строку; а необязательные аргументы такие же, как и для функции ввода текста. Функция получения должна возвращать значение самого типа данных. Обычно функция получения должна объявляться как строгая (STRICT); если это не так, при прочтении входного значения NULL она будет вызываться с первым параметром NULL. В этом случае функция все равно должна возвращать NULL, иначе возникнет ошибка. (Этот случай в основном предназначен для поддержки функций ввода доменных типов, которым может понадобиться отклонять входные данные NULL.) Аналогично необязательная функция_отправки преобразует данные из внутреннего представления во внешнее двоичное представление. Если эта функция не указана, тип не может участвовать в двоичном выводе. Функция отправки должна объявляться как принимающая один аргумент нового типа данных, а возвращать тип bytea. Функции отправки не вызываются для значений NULL.
На этом этапе может возникнуть вопрос, как функции ввода и вывода могут быть
объявлены с результатами или аргументами нового типа, если они должны быть созданы
до создания нового типа. Ответ прост: тип сначала должен быть определен как
тип-оболочка, который является заготовкой и не имеет никаких свойств, кроме имени
и владельца. Он объявляется командой CREATE TYPE имя
без дополнительных
параметров. Затем, ссылаясь на этот пустой тип, можно будет определить функции
ввода/вывода. Наконец, команда CREATE TYPE
с полным определением заменит
тип-оболочку на полное, допустимое определение типа, после чего новый тип можно
будет использовать как обычно.
Необязательные функция_ввода_модификатора_типа и функция_вывода_модификатора_типа необходимы, если тип поддерживает модификаторы, то есть дополнительные ограничения, связанные с объявлением типа, например char(5) или numeric(30,2). QHB позволяет создавать типы, которые могут принимать в качестве модификаторов одну или несколько простых констант или идентификаторов. Однако эта информация должна быть упакована в одно неотрицательное целочисленное значение для хранения в системных каталогах. функция_ввода_модификатора_типа получает объявленный модификатор (или модификаторы) в виде строки cstring. Функция должна проверить значения на допустимость (и вызвать ошибку, если они неверны) и, если они верны, выдать одно неотрицательное значение integer, которое будет сохранено в столбце «typmod». Модификаторы типа будут отклонены, если функция_ввода_модификатора_типа для типа не указана. функция_вывода_модификатора_типа преобразует внутреннее целочисленное значение typmod обратно в правильную форму для отображения пользователю. Она должна вернуть значение cstring, которое именно в таком виде добавляется к имени типа; например, функция numeric должна вернуть (30,2). функцию_вывода_модификатора_типа можно опустить; в этом случае отображением по умолчанию будет сохраненное целочисленное значение typmod, заключенное в круглые скобки.
Необязательная функция_анализа выполняет сбор специфичной для типа статистики
по столбцам с этим типом данных. По умолчанию команда ANALYZE
попытается собрать
статистику, используя операторы «равно» и «меньше, чем», если для типа определен
класс операторов B-дерева по умолчанию. Для нескалярных типов такое поведение в
большинстве случаев не подходит, поэтому его можно переопределить, указав собственную
функцию анализа. Функция анализа должна быть объявлена как принимающая один аргумент
типа internal и возвращающая результат boolean.
Необязательная функция_обращения_по_индексу позволяет обращаться к этому типу данных по индексу в командах SQL. Указание этой функции не заставляет рассматривать данный тип как «истинный» массив; например, он не станет кандидатом в тип результата конструкций ARRAY[]. Но если добавление индекса к значению типа является естественной нотацией для извлечения из него данных, то написание функции_обращения_по_индексу позволяет определить, что это означает. Функция обращения по индексу должна объявляться как принимающая один аргумент типа internal и возвращающая результат internal, который является указателем на структуру с методами (функциями), реализующими обращение по индексу.
Дополнительная информация представлена в параграфе Типы массивов ниже.
Хотя подробные сведения о внутреннем представлении нового типа известны только функциям ввода/вывода и другим функциям, созданным для работы с этим типом, существует еще несколько свойств внутреннего представления, которые должны быть объявлены в QHB. Прежде всего, это внутренняя_длина. Базовый тип данных может быть фиксированной длины, и тогда внутренняя_длина указывается в виде положительного целого числа, а если это тип переменной длины, то во внутренней_длине задается значение VARIABLE. (Внутри же typlen принимает значение -1.) Внутреннее представление всех типов переменной длины должно начинаться с 4-байтового целого числа, задающего общую длину этого значения типа. (Обратите внимание, что поле длины часто кодируется, как описано в разделе TOAST; неразумно обращаться к нему напрямую.)
Необязательный флаг PASSEDBYVALUE показывает, что значения создаваемого типа данных передаются по значению, а не по ссылке. Типы, передаваемые по значению, должны быть фиксированной длины, и их внутреннее представление не может быть больше размера типа Datum (4 байта на одних машинах, 8 байт на других).
Параметр выравнивание указывает, как требуется выравнивать данные этого типа. Допустимые значения выравнивания по границам: 1, 2, 4 или 8 байт. Обратите внимание, что типы переменной длины должны иметь выравнивание не менее 4 байт, так как они обязательно содержат в качестве первого компонента int4.
Параметр хранение позволяет выбирать стратегии хранения для типов данных переменной длины. (Для типов фиксированной длины допускается только вариант plain.) Вариант plain указывает, что данные этого типа всегда будут храниться внутри и не будут сжаты. Вариант extended указывает, что система сначала попытается сжать длинное значение данных, а затем, если оно и после сжатия окажется слишком длинным, переместит его из строки основной таблицы. Вариант external позволяет переместить значение из основной таблицы, но система не будет пытаться сжать его. Вариант main разрешает сжатие, но препятствует перемещению значения из основной таблицы. (Элементы данных с этим вариантом хранения все равно можно переместить из основной таблицы, если нет другого способа уместить их в строке, но предпочтение будет отдано сохранению в основной таблице, в отличие от вариантов extended и external.)
Все значения параметра хранение, кроме plain, подразумевают, что функции
типа данных могут принимать значения в формате toast, как описано в разделе
TOAST и подразделе Использование TOAST. Такое значение просто определяет
вариант хранения TOAST по умолчанию для столбцов отделяемого в TOAST типа данных;
другие стратегии для отдельных столбцов можно выбирать с помощью команды
ALTER TABLE SET STORAGE
.
Параметр тип_образец предоставляет альтернативный метод для указания основных свойств представления типа данных: скопировать их из другого существующего типа. Из указанного типа будут скопированы значения свойств внутренняя_длина, передача_по_значению, выравнивание и хранение. (Можно, хотя обычно это нежелательно, переопределить некоторые из этих значений, указав их вместе с предложением LIKE) Указывать представление типа таким образом особенно удобно при низкоуровневой реализации нового типа, которая некоторым образом «опирается» на существующий тип.
Параметры категория и предпочитаемый могут использоваться для поддержки в управлении тем, какое неявное приведение будет применяться в неоднозначных ситуациях. Каждый тип данных относится к категории, обозначаемой одним символом ASCII, и каждый тип в этой категории является либо «предпочтительным» либо нет. Синтаксический анализатор постарается выбрать приведение к предпочтительному типу (но только из других типов в той же категории), когда это правило может помочь при разрешении перегруженных функций или операторов. Более подробную информацию см. в главе PL/pgSQL. Для типов, которые не имеют неявных приведений к какому-либо другому типу или из него, достаточно оставить значения по умолчанию. Однако для группы связанных типов, которые имеют неявные приведения, часто бывает полезно пометить их все как принадлежащие к категории и выбрать один или два «наиболее общих» типа как предпочтительные в этой категории. Параметр категория особенно полезен при добавлении пользовательского типа в существующую встроенную категорию, например числовые или строковые типы. Однако также можно создавать новые, полностью пользовательские категории типов. В качестве имени такой категории можно выбрать любой ASCII-символ, кроме латинской заглавной буквы.
В случае, если пользователь желает назначить столбцам с этим типом данных значение по умолчанию, отличное от NULL, его можно указать в этой команде после ключевого слова DEFAULT. (Такое значение по умолчанию может быть переопределено явным предложением DEFAULT, добавленным при создании определенного столбца.)
Чтобы указать, что тип является массивом постоянной длины, задайте тип элементов
массива с помощью ключевого слова ELEMENT. Например, чтобы определить массив
4-байтовых целых чисел (int4), задайте ELEMENT = int4
. Дополнительная
информация представлена в параграфе Типы массивов ниже.
Для указания разделителя, который будет использоваться между значениями во внешнем представлении массивов этого типа, можно установить в параметре разделитель определенный символ. Разделителем по умолчанию является запятая (,). Обратите внимание, что разделитель связан с типом элементов массива, а не с самим типом массива.
Если в необязательном логическом параметре сортируемый установлено значение true, определения столбцов и выражения этого типа могут содержать информацию о правилах сортировки, в предложении COLLATE. Получение фактической пользы от этих правил зависит от реализаций функций, работающих с типом; просто от того, что тип помечен как сортируемый, эти правила действовать не будут.
Типы массивов
Каждый раз при создании пользовательского типа QHB автоматически создает связанный тип массива, имя которого состоит из имени типа элемента и знака подчеркивания перед ним. При необходимости полученное имя усекается, если его длина превышает NAMEDATALEN байт. (Если имя, созданное таким образом, конфликтует с именем существующего типа, процесс повторяется до тех пор, пока не будет найдено непротиворечивое имя.) Этот неявно созданный тип массива имеет переменную длину и использует встроенные функции ввода и вывода array_in и array_out. Более того, именно этот тип система использует для конструкций вроде ARRAY[] поверх пользовательского типа. Тип массива отражает любые изменения владельца или схемы его типа элемента и удаляется при удалении типа элемента.
Вы можете задать вопрос, зачем существует параметр ELEMENT, если система создает правильный тип массива автоматически. Единственный случай, когда полезно использовать ELEMENT, это когда вы создаете тип фиксированной длины, который внутренне оказывается массивом нескольких одинаковых элементов, и вы хотите, чтобы эти элементы были доступны напрямую путем обращения по индексу, в дополнение к любым операциям, которые вы планируете реализовать для типа в целом. Например, тип point представляется в виде двух чисел с плавающей запятой, доступ к которым можно получить с помощью point[0] и point[1]. Обратите внимание, что эта возможность работает только с типами фиксированной длины, внутренняя форма которых представляет собой точную последовательность одинаковых полей фиксированной длины. По историческим причинам (т. е. это определенно некорректно, но слишком поздно это менять), индексы в массивах фиксированной длины начинаются с нуля, а не с единицы, как у массивов переменной длины.
Указание параметра SUBSCRIPT позволяет обращаться к типу данных по индексу, даже если в ином случае система не считает его типом массива. Поведение, описанное выше для массивов фиксированной длины, фактически реализуется функцией raw_array_subscript_handler, являющейся обработчиком SUBSCRIPT, которая используется автоматически при указании для типа фиксированной длины параметра ELEMENT, но не параметра SUBSCRIPT.
Когда задается нестандартная функция SUBSCRIPT, указывать ELEMENT обязательно, только если функция обработки SUBSCRIPT должна узнать typelem, чтобы понять, какой тип возвращать. Учтите, что с указанием ELEMENT система будет предполагать, что новый тип содержит тип элемента или каким-то образом физически зависит от него; таким образом, к примеру, нельзя будет изменить свойства типа элемента, если имеются какие-либо столбцы зависимого типа.
Параметры
имя
Имя создаваемого типа (может быть дополнено схемой).
имя_атрибута
Имя атрибута (столбца) для составного типа.
тип_данных
Имя существующего типа данных, который станет столбцом составного типа.
правило_сортировки
Имя существующего правила сортировки, которое будет связано со столбцом составного типа или с диапазонным типом.
метка
Строковый литерал, представляющий текстовую метку, связанную с одним значением перечислимого типа.
подтип
Имя типа элемента, который будет представлять диапазоны для диапазонного типа.
класс_операторов_подтипа
Имя класса операторов B-дерева для подтипа.
каноническая_функция
Имя функции канонизации для диапазонного типа.
функция_разницы_подтипа
Имя функции разницы для данного подтипа.
имя_мультидиапазонного_типа
Имя соответствующего мультидиапазонного типа.
функция_ввода
Имя функции, преобразующей данные из внешней текстовой формы типа в его внутреннюю форму.
функция_вывода
Имя функции, преобразующей данные из внутренней формы типа во внешнюю текстовую форму.
функция_получения
Имя функции, преобразующей данные из внешней двоичной формы типа в его внутреннюю форму.
функция_отправки
Имя функции, преобразующей данные из внутренней формы типа в его внешнюю двоичную форму.
функция_ввода_модификатора_типа
Имя функции, преобразующей массив модификаторов для данного типа во внутреннюю форму.
функция_вывода_модификатора_типа
Имя функции, преобразующей внутреннюю форму модификатора (или модификаторов) типа во внешнюю текстовую форму.
функция_анализа
Имя функции, выполняющей статистический анализ для этого типа данных.
внутренняя_длина
Числовая константа, задающая длину внутреннего представления нового типа в байтах. По умолчанию предполагается, что тип имеет переменную длину.
выравнивание
Требуемое выравнивание для типа данных. Если указано, то допустимые значения: char, int2, int4 или double; значение по умолчанию — int4.
хранение
Стратегия хранения для этого типа данных. Если указана, то допустимые значения: plain, external, extended или main; значение по умолчанию — plain.
тип_образец
Имя существующего типа данных, от которого новый тип получит свойства представления.
Будут скопированы значения следующих параметров этого типа: внутренняя_длина,
передача_по_значению, выравнивание и хранение — если только
они не будут переопределены явными указаниями в этой команде CREATE TYPE
.
категория
Код категории (один символ ASCII) для этого типа. Значение по умолчанию: 'U', что означает «пользовательский тип» (user-defined). Другие коды категорий можно найти в таблице Таблица кодов категорий. Также можно выбрать другие символы ASCII для создания нестандартных категорий.
предпочитаемый
True? если этот тип является предпочтительным типом в своей категории типов, иначе false. Значение по умолчанию — false. Будьте очень осторожны при создании нового предпочтительного типа в рамках существующей категории типов, так как это может вызвать неожиданные изменения в поведении.
по_умолчанию
Значение по умолчанию для данного типа данных. Если этот параметр опущен, значение по умолчанию равно NULL.
элемент
Создаваемый тип является массивом; это параметр определяет тип элементов массива.
разделитель
Символ-разделитель, используемый между значениями в массивах, образованных из значений этого типа.
сортируемый
True, если в операциях с этим типом может учитываться информация о правиле сортировки. Значение по умолчанию равно false.
Примечания
Поскольку нет никаких ограничений на использование типа данных после его создания, создание базового или диапазонного типа равносильно предоставлению всем права на выполнение функций, упомянутых в определении этого типа. Это обычно не является проблемой для тех функций, которые используются в определении типа. Но стоит подумать дважды, прежде чем создавать тип, преобразование которого во внешнюю форму и обратно потребует использования «секретной» информации.
Имя генерируемого типа массива обычно образуется из имени типа элемента и добавленного перед ним символа подчеркивания (_), но оно может быть и другим в случае достижения максимальной длины имени или конфликтов с именами пользовательских типов, начинающихся с подчеркивания. Поэтому написание кода, полагающегося на это соглашение, считается устаревшим подходом. Вместо этого для определения типа массива, связанного с данным типом, лучше воспользоваться pg_type.typarray.
Рекомендуется вообще избегать использования имен типов и таблиц, начинающихся с символа подчеркивания. Хотя сервер сможет сгенерировать другое имя типа массива, чтобы избежать конфликтов с пользовательскими именами, по-прежнему существует риск возникновения путаницы, особенно со старыми клиентскими приложениями, которые могут предположить, что имена типов, начинающиеся с подчеркивания, относится к типу массива.
Примеры
В этом примере создается составной тип, который затем используется в определении функции:
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
);
Дополнительные примеры, включая соответствующие функции ввода и вывода, приведены в разделе Пользовательские типы.
Совместимость
Первая форма команды CREATE TYPE
, которая создает составной тип, соответствует
стандарту SQL. Другие формы являются расширением QHB. Команда
CREATE TYPE
в стандарте SQL также имеет другие формы, которые не реализованы в
QHB.
Возможность создания составного типа без атрибутов является специфическим для
QHB отклонением от стандарта (аналогично CREATE TABLE
).