CREATE TYPE

CREATE TYPE — define um novo tipo de dados

Sinopse

CREATE TYPE nome AS
    ( [ nome_do_atributo tipo_de_dados [ COLLATE ordenação ] [, ... ] ] )

CREATE TYPE nome AS ENUM
    ( [ 'rótulo' [, ... ] ] )

CREATE TYPE nome AS RANGE (
    SUBTYPE = subtipo
    [ , SUBTYPE_OPCLASS = classe_de_operador_do_subtipo ]
    [ , COLLATION = ordenação ]
    [ , CANONICAL = função_de_canonização ]
    [ , SUBTYPE_DIFF = função_de_diferença_de_subtipo ]
    [ , MULTIRANGE_TYPE_NAME = nome_do_tipo_multi_intervalo ]
)

CREATE TYPE nome (
    INPUT = função_de_entrada,
    OUTPUT = função_de_saída
    [ , RECEIVE = função_de_recepção ]
    [ , SEND = função_de_envio ]
    [ , TYPMOD_IN = função_de_entrada_do_modif_de_tipo ]
    [ , TYPMOD_OUT = função_de_saída_do_modif_de_tipo ]
    [ , ANALYZE = função_de_análise_estatística ]
    [ , SUBSCRIPT = função_de_índice ]
    [ , INTERNALLENGTH = { comprimento_interno | VARIABLE } ]
    [ , PASSEDBYVALUE ]
    [ , ALIGNMENT = alinhamento ]
    [ , STORAGE = armazenamento ]
    [ , LIKE = como_o_tipo ]
    [ , CATEGORY = categoria ]
    [ , PREFERRED = preferido ]
    [ , DEFAULT = padrão ]
    [ , ELEMENT = elemento ]
    [ , DELIMITER = delimitador ]
    [ , COLLATABLE = ordenável ]
)

CREATE TYPE nome

Descrição

O comando CREATE TYPE registra um novo tipo de dados para uso no banco de dados corrente [145]. O usuário que define o tipo de dados torna-se seu dono.

Se for fornecido um nome de esquema, o tipo de dados será criado no esquema especificado. Caso contrário, será criado no esquema corrente. O nome do tipo de dados deve ser diferente do nome de qualquer tipo de dados ou domínio existente no mesmo esquema. (Como as tabelas têm tipos de dados associados, o nome do tipo de dados também deve ser diferente do nome de qualquer tabela existente no mesmo esquema.)

Existem cinco formas do comando CREATE TYPE, conforme mostrado na sinopse de sintaxe acima. Estas formas criam, respectivamente, um tipo de dados composto, um tipo de dados enum, um tipo de dados intervalo, um tipo de dados base (escalar), e um tipo de dados shell (esqueleto). Os primeiros quatro são discutidos sucessivamente a seguir. O tipo shell é simplesmente um espaço reservado para um tipo de dados a ser definido posteriormente; é criado executando CREATE TYPE sem parâmetros, exceto o nome do tipo de dados. Os tipos de shell são necessários como referências diretas ao criar tipos intervalo e tipos base, conforme discutido nas respectivas seções.

Tipos compostos

A primeira forma do comando CREATE TYPE cria um tipo de dados composto. O tipo de dados composto é especificado por uma lista de nomes de atributos e tipos de dados. A ordenação do atributo também pode ser especificada, se o tipo de dados for ordenável. Um tipo de dados composto é essencialmente o mesmo que o tipo de dados da linha de uma tabela, mas usar CREATE TYPE evita a necessidade de criar uma tabela real quando tudo o que se deseja é definir um tipo de dados. O tipo de dados composto autônomo é útil, por exemplo, como argumento, ou como o tipo de dados retornado por uma função.

Para poder criar um tipo de dados composto, deve-se ter o privilégio USAGE em todos os tipos de dados dos atributos.

Tipos enumerados

A segunda forma do comando CREATE TYPE cria um tipo de dados enumerado (enum), conforme descrito em Tipos de dados de enumeração. Os tipos de enumeração recebem uma lista de rótulos entre apóstrofos, cada um dos quais deve ter menos de NAMEDATALEN bytes (64 bytes em uma compilação padrão do PostgreSQL). (É possível criar um tipo de dados enumerado com zero rótulos, mas este tipo de dados não poderá ser usado para conter valores antes que pelo menos um rótulo seja adicionado usando o comando ALTER TYPE.)

Tipos intervalo

A terceira forma do comando CREATE TYPE cria um tipo de dados intervalo, conforme descrito em Tipos de dados de intervalo.

O subtipo do tipo de dados intervalo pode ser qualquer tipo de dados com uma classe de operador árvore-B associada (para determinar a ordem dos valores para o tipo de dados intervalo). Normalmente, a classe de operador de árvore-B padrão do subtipo é usada para determinar a ordenação; para usar uma classe de operador não padrão, deve ser especificado seu nome em classe_de_operador_do_subtipo. Se o subtipo for ordenável, e se desejar usar uma ordenação não-padrão para ordenação do intervalo, deve ser especificada a ordenação desejada na opção ordenação.

A função opcional função_de_canonização deve receber um argumento do tipo de dados intervalo que está sendo definido, e retornar um valor do mesmo tipo de dados. Esta função é usada para converter valores de intervalo na forma canônica, quando aplicável. Veja Definição de novos tipos de dados de intervalo para obter mais informações. Criar uma função_de_canonização é um pouco complicado, porque deve ser definida antes que o tipo de dados intervalo possa ser declarado. Para fazer isto, deve-se primeiro criar um tipo de dados shell, que é um tipo de dados de reserva de espaço, que não possui propriedades, exceto o nome e o dono. Isto é feito executando o comando CREATE TYPE nome, sem parâmetros adicionais. Em seguida, a função poderá ser declarada usando o tipo de dados shell como argumento e resultado e, finalmente, o tipo de dados intervalo poderá ser declarado usando o mesmo nome. Isto substitui automaticamente a entrada do tipo de dados shell por um tipo de dados intervalo válido.

A função opcional função_de_diferença_de_subtipo deve receber dois valores do tipo de dados do subtipo como argumento, e retornar um valor do tipo de dados double precision representando a diferença entre os dois valores fornecidos. Embora esta função seja opcional, fornecê-la permite uma eficiência muito maior dos índices GiST em colunas do tipo de dados intervalo. Veja Definição de novos tipos de dados de intervalo para obter mais informações.

O parâmetro opcional nome_do_tipo_multi_intervalo especifica o nome do tipo de dados multi-intervalo correspondente. Se não for especificado, este nome será escolhido automaticamente da seguinte maneira. Se o nome do tipo de dados intervalo contiver a sub-cadeia de caracteres range, então o nome do tipo de dados multi-intervalo será formado pela substituição da sub-cadeia de caracteres range por multirange no nome do tipo de dados intervalo. Caso contrário, o nome do tipo de dados multi-intervalo será formado anexando um sufixo _multirange ao nome do tipo de dados intervalo.

Tipos base

A quarta forma do comando CREATE TYPE cria um tipo de dados base (tipo de dados escalar). Para criar um tipo de dados base, é necessário ser um superusuário. (Esta restrição ocorre porque uma definição de tipo de dados errônea pode confundir, ou até mesmo travar, o servidor.)

Os parâmetros podem aparecer em qualquer ordem, e não apenas na ordem mostrada acima, e a maioria é opcional. Devem ser registradas duas ou mais funções (usando o comando CREATE FUNCTION) antes de definir o tipo de dados. As funções de suporte função_de_entrada e função_de_saída são requeridas, enquanto as funções função_de_recepção, função_de_envio, função_de_entrada_do_modif_de_tipo, função_de_saída_do_modif_de_tipo, função_de_análise_estatística, e função_de_índice são opcionais. Geralmente estas funções devem ser codificadas em C, ou outra linguagem de baixo nível.

A função_de_entrada converte a representação textual externa do tipo de dados para a representação interna utilizada pelos operadores e funções definidas para o tipo de dados. A função_de_saída realiza a transformação inversa. A função de entrada pode ser declarada como recebendo um argumento do tipo de dados cstring, ou como recebendo três argumentos dos tipos de dados cstring, oid, e integer. O primeiro argumento é o texto de entrada como uma cadeia de caracteres C, o segundo argumento é o próprio OID do tipo de dados (exceto para tipos de dados matriz, que em vez disso recebem o OID do tipo de dados de seus elementos), e o terceiro é o typmod da coluna de destino, se conhecido (será passado -1, se não for conhecido). A função de entrada deve retornar um valor do próprio tipo de dados. Normalmente, a função de entrada deve ser declarada como estrita (STRICT); se não for, será chamada com o primeiro parâmetro NULL ao ler um valor de entrada NULL. A função ainda deve retornar NULL neste caso, a menos que relate um erro. (Este caso destina-se principalmente a oferecer suporte a funções de entrada de domínio, que podem precisar rejeitar entradas NULL.) A função de saída deve ser declarada como recebendo um argumento do novo tipo de dados. A função de saída deve retornar o tipo de dados cstring. As funções de saída não são chamadas para valores NULL.

A função_de_recepção opcional converte a representação binária externa do tipo de dados para a representação interna. Se esta função não for fornecida, o tipo de dados não poderá participar de entrada binária. A representação binária deve ser escolhida de forma a custar pouco para converter para a forma interna, enquanto seja razoavelmente portátil. (Por exemplo, os tipos de dados inteiros padrão usam a ordem de byte da rede como representação binária externa, enquanto a representação interna está na ordem de byte nativa da máquina.) A função de recepção deve executar a verificação adequada para garantir que o valor seja válido. A função de recepção pode ser declarada como aceitando um argumento do tipo de dados internal, ou como recebendo três argumentos dos tipos de dados internal, oid, e integer. O primeiro argumento é um ponteiro para um buffer do tipo de dados StringInfo (veja Tipos de dados definidos pelo usuário), contendo a cadeia de bytes recebida; os argumentos opcionais são os mesmos da função de entrada de texto. A função de recepção deve retornar um valor do próprio tipo de dados. Normalmente, uma função de recepção deve ser declarada como estrita (STRICT); se não for, será chamada com o primeiro parâmetro NULL ao ler um valor de entrada NULL. A função ainda deverá retornar NULL neste caso, a menos que relate um erro. (Este caso destina-se principalmente a oferecer suporte a funções de recepção de domínio, que podem precisar rejeitar entradas NULL.) Da mesma forma, a função_de_envio opcional converte da representação interna para a representação binária externa. Se esta função não for fornecida, o tipo de dados não poderá participar da saída binária. A função de envio deve ser declarada como recebendo um argumento do novo tipo de dados. A função de envio deve retornar o tipo de dados bytea. As funções de envio não são chamadas para valores NULL.

Neste ponto, deve-se estar se perguntando como as funções de entrada e saída podem ser declaradas para ter resultados ou argumentos do novo tipo de dados, quando elas precisam ser criadas antes que o novo tipo de dados possa ser criado. A resposta é que o tipo de dados deve ser primeiro definido como um tipo de dados shell (esqueleto), que é um tipo de dados de espaço reservado que não possui propriedades, exceto o nome e o dono. Isto é feito executando o comando CREATE TYPE nome, sem parâmetros adicionais. Então as funções C de E/S podem ser definidas referenciando o tipo de dados shell. Por fim, o comando CREATE TYPE com uma definição completa irá substituir a entrada do tipo de dados shell por uma definição de tipo de dados completa e válida, após a qual o novo tipo de dados poderá ser usado normalmente.

As funções opcionais função_de_entrada_do_modif_de_tipo e função_de_saída_do_modif_de_tipo são necessárias se o tipo de dados oferecer suporte a modificadores, ou seja, restrições opcionais anexadas a uma declaração de tipo de dados, como char(5) ou numeric(30,2). O PostgreSQL permite que tipos de dados definidos pelo usuário usem uma, ou mais, constantes ou identificadores simples como modificadores. Entretanto, estas informações devem poder ser comprimidas em um único valor inteiro não negativo para armazenamento nos catálogos do sistema. À função_de_entrada_do_modif_de_tipo é passado o(s) modificador(es) declarado(s) na forma de uma matriz cstring. Esta função deverá verificar a validade dos valores (relatando um erro se estiverem errados) e, se estiverem corretos, retornar um único valor integer não negativo que será armazenado como a coluna typmod. Os modificadores de tipo de dados serão rejeitados se o tipo de dados não tiver uma função_de_entrada_do_modif_de_tipo. A função_de_saída_do_modif_de_tipo converte o valor typmod inteiro interno de volta para a forma correta para mostrar ao usuário. A função deverá retornar um valor cstring, que é a cadeia de caracteres exata a ser anexada ao nome do tipo de dados; por exemplo, a função numeric pode retornar (30,2). É permitido omitir a função_de_saída_do_modif_de_tipo, caso em que o formato de exibição padrão é apenas o valor inteiro de typmod armazenado, entre parênteses.

A função_de_análise_estatística opcional executa coleta de estatísticas específicas do tipo de dados para colunas do tipo de dados. Por padrão, o comando ANALYZE tentará reunir estatísticas usando os operadores igual a e menor que do tipo de dados, se houver uma classe de operador árvore-B padrão para o tipo de dados. Para tipos de dados não escalares, este comportamento provavelmente não é adequado, portanto, pode ser substituído especificando uma função de análise personalizada. A função de análise deve ser declarada recebendo um único argumento do tipo de dados internal, e retornar um resultado do tipo de dados boolean. A API detalhada para funções de análise está documentada no arquivo src/include/commands/vacuum.h (arquivo de cabeçalho para o vacuum cleaner e analisador de estatísticas do postgres).

A função_de_índice opcional permite que o tipo de dados seja indexado em comandos SQL. Especificar esta função não faz com que o tipo de dados seja considerado um tipo de dados matriz verdadeiro; por exemplo, não será um candidato para o tipo de dados de resultado das construções ARRAY[]. Mas se indexar um valor do tipo de dados for uma notação natural para extrair dados dele, então poderá ser escrita uma função_de_índice para definir o que isto significa. A função de índice deve ser declarada recebendo um único argumento do tipo de dados internal, e retornando um resultado do tipo de dados internal, que é um ponteiro para uma estrutura de métodos (funções) que implementam a indexação. A API detalhada para funções de índice está documentada no arquivo src/include/nodes/subscripting.h (API para indexação de tipo de dados genérico). Também pode ser útil ler a implementação de matriz no arquivo src/backend/utils/adt/arraysubs.c (funções de suporte a indexação para matrizes), ou o código mais simples no arquivo contrib/hstore/hstore_subs.c (funções de suporte a indexação para hstore). Informações adicionais são encontradas em Tipos matriz abaixo.

Embora os detalhes da representação interna do novo tipo de dados sejam conhecidos apenas pelas funções de E/S, e outras funções criadas para trabalhar com o tipo de dados, há várias propriedades da representação interna que devem ser declaradas para o PostgreSQL. A mais importante delas é o comprimento_interno. Os tipos de dados base podem ter comprimento fixo, caso em que o comprimento_interno é um número inteiro positivo, ou ter comprimento variável, indicado definindo o comprimento_interno como VARIABLE. (Internamente, isto é representado definindo typlen como -1.) A representação interna de todos os tipos de dados de comprimento variável deve começar com um inteiro de 4 bytes fornecendo o comprimento total desse valor do tipo de dados. (Note que o campo de comprimento é geralmente codificado conforme descrito em TOAST; não é aconselhável acessá-lo diretamente.)

O sinalizador opcional PASSEDBYVALUE indica que os valores desse tipo de dados são passados por valor, em vez de por referência. Os tipos de dados passados por valor devem ter comprimento fixo, e sua representação interna não pode ser maior que o tamanho do tipo de dados Datum (4 bytes em algumas máquinas, 8 bytes em outras).

O parâmetro alinhamento especifica o alinhamento de armazenamento necessário para o tipo de dados. Os valores permitidos equivalem ao alinhamento em limites de 1, 2, 4 ou 8 bytes. Note que os tipos de dados de comprimento variável devem ter um alinhamento de pelo menos 4, porque necessariamente contêm um int4 como seu primeiro componente.

O parâmetro armazenamento permite a seleção de estratégias de armazenamento para tipos de dados de tamanho variável. (Somente é permitido plain para tipos de dados de comprimento fixo.) plain especifica que os dados desse tipo de dados serão sempre armazenados em-linha e não comprimidos. extended especifica que o sistema primeiro tentará comprimir um valor de dados longo, e moverá o valor para fora da linha da tabela principal se ainda assim for muito longo. external permite que o valor seja movido para fora da tabela principal, mas o sistema não tentará comprimi-lo. main permite compressão, mas desencoraja mover o valor para fora da tabela principal. (Os itens de dados com esta estratégia de armazenamento ainda poderão ser movidos para fora da tabela principal se não houver outra maneira de ajustar a linha, mas serão preferencialmente mantidos na tabela principal, ao contrário dos itens extended e external.)

Todos os valores de armazenamento diferentes de plain, implicam que as funções do tipo de dados podem lidar com valores que foram colocados em TOAST, conforme descrito em TOAST e Considerações sobre o TOAST. O outro valor específico fornecido determina a estratégia de armazenamento padrão em TOAST para as colunas de um tipo de dados que pode ser armazenado externamente; os usuários podem escolher outras estratégias para colunas individuais usando o comando ALTER TABLE SET STORAGE.

O parâmetro como_o_tipo fornece um método alternativo para especificar as propriedades básicas de representação de um tipo de dados: copiá-los de algum tipo de dados existente. Os valores de comprimento_interno, passado_por_valor, alinhamento, e armazenamento, são copiados do tipo de dados indicado. (É possível, embora geralmente não desejado, substituir alguns desses valores especificando-os junto com a cláusula LIKE.) Especificar a representação desta forma é especialmente útil quando a implementação de baixo nível do novo tipo de dados se apoia (piggybacks) em um tipo de dados existente de alguma forma.

Os parâmetros categoria e preferido podem ser usados para ajudar a controlar qual conversão implícita será aplicada em situações ambíguas. Cada tipo de dados pertence a uma categoria identificada por um único caractere ASCII, e cada tipo de dados é preferido ou não dentro de sua categoria. O analisador irá preferir converter para tipos de dados preferidos (mas apenas de outros tipos de dados dentro da mesma categoria) quando esta regra servir para resolver funções ou operadores sobrecarregados. Para obter mais detalhes, veja Conversão de tipo de dados. Para tipos de dados que não têm conversões implícitas de ou para quaisquer outros tipos de dados, é suficiente deixar estas configurações com seus padrões. Entretanto, para um grupo de tipos de dados relacionados que possuem conversões implícitas, geralmente é útil marcá-los todos como pertencentes a uma categoria, e selecionar um ou dois dos tipos de dados mais gerais como preferidos na categoria. O parâmetro categoria é especialmente útil ao adicionar um tipo de dados definido pelo usuário a uma categoria interna existente, como os tipos de dados numéricos ou de cadeia de caracteres. Entretanto, também é possível criar novas categorias de tipo de dados totalmente definidas pelo usuário. Deve-se selecionar qualquer caractere ASCII diferente de uma letra maiúscula para representar esta categoria.

Pode ser especificado um valor padrão, no caso do usuário desejar que as colunas do tipo de dados sejam padronizadas para algo diferente do valor nulo. O padrão é especificado com a palavra-chave DEFAULT. (Este valor padrão pode ser mudado por uma cláusula DEFAULT explícita anexada a uma coluna específica.)

Para indicar que o tipo de dados é um tipo de dados matriz de comprimento fixo, deve ser especificado o tipo de dados dos elementos da matriz usando a palavra-chave ELEMENT. Por exemplo, para definir uma matriz de inteiros de 4 bytes (int4), deve ser especificado ELEMENT = int4. Para obter mais detalhes, veja Tipos matriz abaixo.

Para indicar o delimitador a ser usado entre os valores na representação externa de matrizes desse tipo de dados, pode-se definir o delimitador como um caractere específico. O delimitador padrão é a vírgula (,). Note que o delimitador está associado ao tipo de dados do elemento da matriz, e não ao próprio tipo de dados matriz.

Se o parâmetro booleano opcional ordenável for verdade, as definições de coluna e expressões do tipo de dados podem carregar informações de ordenação através do uso da cláusula COLLATE. Cabe às implementações das funções que operam no tipo de dados realmente fazer uso das informações de ordenação; isto não acontece automaticamente apenas marcando o tipo de dados como ordenável.

Tipos matriz

Sempre que é criado um tipo de dados definido pelo usuário, o PostgreSQL cria automaticamente um tipo de dados matriz associado, cujo nome consiste no nome do tipo de dados do elemento, prefixado com um sublinhado, e truncado, se necessário, para mantê-lo com menos de NAMEDATALEN bytes de comprimento. (Se o nome assim gerado colidir com outro nome de tipo de dados existente, o processo será repetido até que seja encontrado um nome não conflitante.) Este tipo de dados matriz criado implicitamente tem comprimento variável, e usa as funções internas de entrada e saída array_in e array_out. Além disso, este tipo de dados é o que o sistema usa para construções como ARRAY[] sobre o tipo de dados definido pelo usuário. O tipo de dados matriz rastreia quaisquer alterações no dono ou esquema de seu tipo de dados do elemento, sendo descartado se o tipo de dados do elemento o for.

Pode-se perguntar por que existe uma opção ELEMENT, se o sistema cria o tipo de dados matriz correto automaticamente. O principal caso onde é útil usar ELEMENT é quando se está criando um tipo de dados de comprimento fixo que é internamente uma matriz de várias coisas idênticas, e se deseja permitir que estas coisas sejam acessadas diretamente por indexação, além de quaisquer operações que se planeje fornecer para o tipo de dados como um todo. Por exemplo, o tipo de dados point é representado como apenas dois números de ponto flutuante, que podem ser acessados usando point[0] e point[1]. Veja que este recurso funciona apenas para tipos de dados de comprimento fixo, cuja forma interna é exatamente uma sequência de campos de comprimento fixo idênticos. Por razões históricas (ou seja, está claramente errado, mas é muito tarde para mudar), a indexação de tipos de dados matriz de comprimento fixo começa por zero, em vez de um, como em matrizes de comprimento variável.

Especificar a opção SUBSCRIPT permite que o tipo de dados seja indexado, mesmo que o sistema não o considere como um tipo de dados matriz. O comportamento recém-descrito para matrizes de comprimento fixo é realmente implementado pela função raw_array_subscript_handler do tratador de SUBSCRIPT, que é usada automaticamente se for especificado ELEMENT para um tipo de dados de comprimento fixo sem também escrever SUBSCRIPT.

Ao especificar uma função personalizada SUBSCRIPT, não é necessário especificar ELEMENT, a menos que a função do tratador de SUBSCRIPT precise consultar typelem para descobrir o que retornar. Esteja ciente de que especificar ELEMENT faz com que o sistema assuma que o novo tipo de dados contém, ou é de alguma forma fisicamente dependente, do tipo de dados do elemento; assim, por exemplo, alterar as propriedades do tipo de dados do elemento não será permitido se houver colunas dependentes do tipo de dados.

Parâmetros

nome

O nome (opcionalmente qualificado pelo esquema) do tipo de dados a ser criado.

nome_do_atributo

O nome do atributo (coluna) para o tipo de dados composto.

tipo_de_dados

O nome do tipo de dados existente a se tornar uma coluna do tipo de dados composto.

ordenação

O nome da ordenação existente a ser associada a uma coluna do tipo de dados composto, ou ao tipo de dados intervalo.

rótulo

Um literal de cadeia de caracteres representando o rótulo textual associado a um valor do tipo de dados de enumeração.

subtipo

O nome do tipo de dados do elemento do qual o tipo de dados intervalo representará os intervalos.

classe_de_operador_do_subtipo

O nome da classe de operador árvore-B para o subtipo.

função_de_canonização

O nome da função de canonização para o tipo de dados intervalo.

função_de_diferença_de_subtipo

O nome da função de diferença para o subtipo.

nome_do_tipo_multi_intervalo

O nome do tipo de dados multi-intervalo correspondente.

função_de_entrada

O nome da função que converte dados da forma textual externa do tipo de dados em sua forma interna.

função_de_saída

O nome da função que converte dados da forma interna do tipo de dados em sua forma textual externa.

função_de_recepção

O nome da função que converte dados do formato binário externo do tipo de dados em seu formato interno.

função_de_envio

O nome da função que converte dados da forma interna do tipo de dados em sua forma binária externa.

função_de_entrada_do_modif_de_tipo

O nome da função que converte uma matriz de modificadores para o tipo de dados em forma interna.

função_de_saída_do_modif_de_tipo

O nome da função que converte a forma interna do(s) modificador(es) do tipo de dados em forma textual externa.

função_de_análise_estatística

O nome da função que executa análise estatística para o tipo de dados.

função_de_índice

O nome da função que define o que indexar um valor do tipo de dados faz.

comprimento_interno

Uma constante numérica que especifica o comprimento em bytes da representação interna do novo tipo de dados. A suposição padrão é que é de comprimento variável.

alinhamento

O requisito de alinhamento de armazenamento do tipo de dados. Se especificado, deverá ser char, int2, int4, ou double; o padrão é int4.

armazenamento

A estratégia de armazenamento para o tipo de dados. Se especificado, deverá ser plain, external, extended, ou main; o padrão é plain.

como_o_tipo

O nome do tipo de dados existente que o novo tipo de dados terá a mesma representação. Os valores de comprimento_interno, passado_por_valor, alinhamento, e armazenamento são copiados desse tipo de dados, a menos que sejam substituídos por especificação explícita em outro lugar no comando CREATE TYPE.

categoria

O código de categoria (um único caractere ASCII) para este tipo de dados. O valor padrão é 'U' para tipo de dados definido pelo usuário. Outros códigos de categoria padrão podem ser encontrados em Tabela 52.65. Também podem ser escolhidos outros caracteres ASCII para criar categorias personalizadas.

preferido

Verdade se este tipo de dados for um tipo preferencial dentro de sua categoria de tipo de dados, caso contrário, falso. O padrão é falso. Deve-se tomar muito cuidado ao criar um novo tipo de dados preferencial dentro de uma categoria de tipo de dados existente, porque isto pode causar mudanças surpreendentes no comportamento.

padrão

O valor padrão para o tipo de dados. Se for omitido, o padrão é nulo.

elemento

O tipo de dados que está sendo criado é uma matriz; especifica o tipo de dados dos elementos da matriz.

delimitador

O caractere delimitador a ser usado entre valores em matrizes feitas desse tipo de dados.

ordenável

Verdade se as operações desse tipo de dados puderem usar informações de ordenação. O padrão é falso.

Notas

Como não há restrições ao uso do tipo de dados após este ser criado, criar um tipo de dados base ou tipo de dados intervalo equivale a conceder permissão de execução pública nas funções mencionadas na definição do tipo de dados. Isto geralmente não é um problema para os tipos de funções que são úteis em uma definição de tipo de dados. Mas pode-se querer pensar duas vezes antes de projetar um tipo de dados de forma que exija informações secretas a serem usadas ao convertê-lo de ou para a forma externa.

Antes do PostgreSQL versão 8.3, o nome do tipo de dados matriz gerado era sempre exatamente o nome do tipo de dados do elemento com um caractere de sublinhado (_) anexado. (Os nomes dos tipos de dados eram, portanto, restritos em comprimento a um caractere a menos do que os outros nomes.) Embora este ainda seja geralmente o caso, o nome do tipo de dados matriz pode variar em caso de nomes de comprimento máximo, ou colisões com nomes de tipo de dados do usuário que começam com sublinhado. Escrever código que depende dessa convenção está, portanto, em obsolescência. Em vez disso, deve-se usar pg_type.typarray para localizar o tipo de dados matriz associado a um determinado tipo de dados.

Pode ser aconselhável evitar o uso de nomes de tipo de dados e tabela começando com sublinhado. Embora o servidor altere os nomes dos tipos de dados matriz gerados para evitar colisões com nomes fornecidos pelo usuário, ainda há o risco de confusão, principalmente com software cliente antigo que pode presumir que os nomes de tipo de dados iniciados com sublinhados sempre representam matrizes.

Antes do PostgreSQL versão 8.2, não existia a sintaxe de criação do tipo de dados shell CREATE TYPE nome. A maneira de criar um tipo de dados base novo era criar primeiro sua função de entrada. Nesta abordagem, o PostgreSQL verá primeiro o nome do novo tipo de dados como o tipo de dados retornado pela função de entrada. O tipo de dados shell é criado implicitamente nesta situação, podendo ser referenciado nas definições das funções de E/S restantes. Esta abordagem ainda funciona, mas está em obsolescência, podendo ser desativada em algum lançamento futuro. Além disso, para evitar sobrecarregar acidentalmente os catálogos com tipos de dados shell como resultado de simples erros de digitação nas definições de função, o tipo de dados shell só será criado dessa maneira quando a função de entrada for escrita em C.

No PostgreSQL versão 16 e posteriores, é recomendável que as funções de entrada dos tipos de dados base retornem erros soft (suaves) usando o novo mecanismo errsave()/ereturn(), em vez de lançar exceções usando a função ereport() como era feito nas versões anteriores. Veja o arquivo src/backend/utils/fmgr/README para obter mais informações.

Exemplos

Este exemplo cria um tipo de dados composto, e o utiliza em uma definição de função:

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

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

Este exemplo cria um tipo de dados enumerado, e o utiliza em uma definição de tabela:

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

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

Este exemplo cria um tipo de dados intervalo:

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

Este exemplo cria o tipo de dados base box, e então o usa em uma definição de tabela:

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
);

Se a estrutura interna de box fosse uma matriz de quatro elementos float4, poderia ser usado

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

o que permitiria que os números dos componentes de um valor de caixa fossem acessados por indexação. Caso contrário, o tipo de dados se comporta da mesma forma que antes.

Este exemplo cria um tipo de dados de objeto grande, e o utiliza em uma definição de tabela:

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

Mais exemplos, incluindo funções de entrada e saída adequadas, podem ser encontradas em Tipos de dados definidos pelo usuário.

Conformidade

A primeira forma do comando CREATE TYPE, que cria um tipo de dados composto, está em conformidade com o padrão SQL. As demais formas são extensões do PostgreSQL. O comando CREATE TYPE no padrão SQL também define outras formas que não são implementadas no PostgreSQL.

A capacidade de criar um tipo de dados composto com zero atributos é uma extensão ao padrão específica do PostgreSQL (análogo ao mesmo caso em CREATE TABLE).

Veja também

ALTER TYPE, CREATE DOMAIN, CREATE FUNCTION, DROP TYPE


[145] O comando CREATE TYPE define um tipo de dados definido pelo usuário no servidor corrente IBM DB2 12.1.x – CREATE TYPE statement (N. T.)