CREATE TYPE

Nome

CREATE TYPE -- cria um tipo de dado

Sinopse

CREATE TYPE nome AS
    ( nome_do_atributo tipo_de_dado [, ... ] )

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 ]
    [ , ANALYZE = função_de_análise ]
    [ , INTERNALLENGTH = { comprimento_interno | VARIABLE } ]
    [ , PASSEDBYVALUE ]
    [ , ALIGNMENT = alinhamento ]
    [ , STORAGE = armazenamento ]
    [ , DEFAULT = padrão ]
    [ , ELEMENT = elemento ]
    [ , DELIMITER = delimitador ]
)

CREATE TYPE nome

Descrição

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

Se for fornecido o nome do esquema, então o tipo será criado no esquema especificado, senão será criado no esquema corrente. O nome do tipo deve ser distinto do nome de qualquer tipo ou domínio existente no mesmo esquema (como as tabelas possuem tipo de dado associado, o nome do tipo também deve ser distinto do nome de qualquer tabela existente no mesmo esquema).

Tipos Compostos

A primeira forma de CREATE TYPE cria um tipo composto. O tipo composto é especificado por uma lista de nomes de atributo e tipos de dado. É essencialmente a mesma coisa que o tipo de uma linha de tabela, mas o uso de CREATE TYPE evita a necessidade de criar uma tabela real quando tudo o que se deseja é definir um tipo de dado. Um tipo composto autônomo é útil como argumento ou tipo retornado por uma função. [4] [5] [6]

Tipos Base

A segunda forma do comando CREATE TYPE cria um novo tipo base (tipo escalar). Os parâmetros podem estar em qualquer ordem, e não apenas na ordem mostrada acima, e a maior parte é opcional. Requer o registro de duas ou mais funções (utilizando CREATE FUNCTION) antes de definir o tipo. 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 e função_de_análise são opcionais. Geralmente estas funções precisam ser codificadas em C ou em outra linguagem de baixo nível.

A função_de_entrada converte a representação textual externa do tipo na representação interna utilizada pelos operadores e funções definidos para o tipo. 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 cstring, ou recebendo três argumentos dos tipos cstring, oid e integer. O primeiro argumento é o texto de entrada como uma cadeia de caracteres C, o segundo argumento é o OID do próprio tipo (exceto para os tipos matriz que, em vez disto, recebem o OID do tipo do elemento), e o terceiro é o typmod da coluna de destino, se for conhecido (será passado -1 se não for conhecido). A função de entrada deve retornar um valor do próprio tipo de dado. Normalmente a função de entrada deve ser declarada como STRICT; se não for, será chamada com o primeiro parâmetro nulo ao ler um valor de entrada nulo. A função ainda deve retornar nulo neste caso, a menos que lance um erro (este caso se destina principalmente a dar suporte às funções de entrada de domínio, que podem precisar rejeitar entradas nulas). A função de saída deve ser declarada como recebendo um argumento do novo tipo de dado. A função de saída deve retornar o tipo cstring. As funções de saída não são chamadas para valores nulos.

A função_de_recepção opcional converte a representação binária externa do tipo para a representação interna. Se esta função não for fornecida, o tipo não poderá participar de entrada binária. A representação binária deve ser escolhida para ser de baixo custo converter para a forma interna, e ao mesmo tempo razoavelmente portável (Por exemplo, os tipos de dado inteiro padrão utilizam a ordem de bytes da rede como sendo a representação binária externa, enquanto a representação interna está na ordem de bytes nativa da máquina). A função de recepção deve realizar uma verificação adequada para garantir que o valor seja válido. A função de recepção pode ser declarada como recebendo um argumento do tipo internal, ou recebendo três argumentos dos tipos internal, oid e integer. O primeiro argumento é um ponteiro para a área StringInfo 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 seu próprio tipo de dado. Normalmente a função de recepção deve ser declarada como STRICT; se não for, será chamada com o primeiro parâmetro nulo ao ler um valor de entrada nulo. A função ainda deve retornar nulo neste caso, a menos que lance um erro (este caso se destina principalmente a dar suporte às funções de recepção de domínio, que podem precisar rejeitar entradas nulas). De forma semelhante, 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 não poderá participar de 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 bytea. As funções de envio não são chamadas para valores nulos.

Neste ponto podemos estar querendo saber como as funções de entrada e de saída podem ser declaradas possuindo resultados ou argumentos do novo tipo, se devem ser criadas antes do novo tipo ser criado. A resposta é que primeiro o tipo deve ser definido como um tipo invólucro, que é um tipo guardador de lugar, e que não possui nenhuma propriedade, exceto o nome e o dono. Isto é feito executando o comando CREATE TYPE nome sem nenhum parâmetro adicional. Depois disso podem ser definidas as funções de E/S fazendo referência ao tipo invólucro. Finalmente, o comando CREATE TYPE com a definição completa substitui a entrada invólucro por uma definição completa e válida, após o que o novo tipo poderá ser utilizado normalmente.

A função_de_análise opcional realiza a coleta de estatísticas específicas do tipo para as colunas com este tipo de dado. Por padrão, o comando ANALYZE tenta obter as estatísticas usando os operadores "igual" e "menor-que" do tipo, se houver uma classe de operadores b-tree padrão para o tipo. Para os tipos não escalares este comportamento provavelmente não será adequado e, portanto, poderá ser substituído especificando uma função de análise personalizada. A função de análise deve ser declarada como recebendo um único argumento do tipo internal, e retornando um resultado do tipo boolean. A API detalhada para funções de análise está descrita em src/include/commands/vacuum.h.

Enquanto os detalhes da representação interna do novo tipo são conhecidos somente pelas funções de entrada e de saída, e por outras funções criadas pelo usuário para trabalhar com o tipo, existem várias propriedades da representação interna que devem ser declaradas para o PostgreSQL. A mais importante destas é o comprimento_interno. Os tipos de dado base podem ser de comprimento fixo e, neste caso, o comprimento_interno é um inteiro positivo, ou de comprimento variável, indicado pela definição do comprimento_interno igual a VARIABLE (Internamente isto é representado definindo typlen como -1). A representação interna de todos os tipos de comprimento variável devem começar por um inteiro de 4 bytes informando o comprimento total deste valor do tipo.

O sinalizador opcional PASSEDBYVALUE indica que os valores deste tipo de dado são passados por valor, e não por referência. Não se deve passar por valor os tipos cuja representação interna é maior do que o tamanho do tipo Datum (4 bytes na maioria das máquinas, e 8 bytes em poucas).

O parâmetro alinhamento especifica o alinhamento de armazenamento requerido por este tipo de dado. Os valores permitidos igualam o alinhamento às fronteiras de 1, 2, 4 ou 8 bytes. Deve ser observado que os tipos de comprimento variável devem ter um alinhamento de pelo menos 4, porque contêm, necessariamente, um int4 como seu primeiro componente.

O parâmetro armazenamento permite selecionar estratégias de armazenamento para tipos de dado de comprimento variável (para os tipos de comprimento fixo somente é permitido plain). plain especifica que os dados deste tipo sempre são armazenados em-linha e não comprimidos. extended especifica que primeiro o sistema irá tentar comprimir o valor de dado longo, e irá mover o valor para fora da linha da tabela principal se ainda permanecer muito longo. external permite mover o valor para fora da tabela principal, mas o sistema não tentará comprimi-lo. main permite a compressão, mas desencoraja mover o valor para fora da tabela principal (os itens de dado com esta estratégia de armazenamento podem ser movidos para fora da tabela principal se não houver outra maneira de encaixá-los na linha, mas têm preferência para serem mantidos na tabela principal em relação aos itens extended e external).

Pode ser especificado um valor padrão quando se deseja que as colunas com este tipo de dado tenham como padrão algo diferente do valor nulo. O valor padrão é especificado pela palavra chave DEFAULT; este padrão pode ser substituído por uma cláusula DEFAULT explícita anexada a uma determinada coluna.

Para indicar que o tipo é uma matriz, deve ser especificado o tipo dos elementos da matriz utilizando a palavra chave ELEMENT. Por exemplo, para definir uma matriz de inteiros de 4 bytes (int4), deve ser especificado ELEMENT = int4. Abaixo são mostrados mais detalhes sobre os tipos matriz.

Para indicar o delimitador a ser utilizado entre os valores na representação externa das matrizes deste tipo, pode-se definir delimitador como um caractere específico. O delimitador padrão é a vírgula (,). Deve ser observado que o delimitador está associado com o tipo do elemento da matriz, e não com a própria matriz.

Tipos matriz

Sempre que é criado um tipo de dado base definido pelo usuário, o PostgreSQL cria automaticamente um tipo matriz (array) associado, cujo nome consiste no nome do tipo base prefixado pelo caractere sublinhado. O analisador compreende esta convenção de nome, e traduz as solicitações para colunas do tipo foo[] em solicitações para o tipo _foo. O tipo matriz criado implicitamente é de comprimento variável e usa as funções de entrada e saída nativas array_in e array_out.

Pode ser perguntado, com razão, por que existe a opção ELEMENT se o sistema produz o tipo matriz correto automaticamente. O único caso onde é útil utilizar ELEMENT é quando se constrói um tipo de comprimento fixo que é internamente uma matriz com um número fixo de elementos idênticos, e se deseja que estes elementos sejam acessados diretamente por índices, além de qualquer outra operação que se planeje fornecer para este tipo como um todo. Por exemplo, o tipo name permite que os elementos char que o constituem sejam acessados desta forma. Um tipo point 2-D pode permitir que os dois números que o compõe sejam acessados como point[0] e point[1]. Deve ser observado que esta praticidade somente funciona para tipos de comprimento fixo cuja forma interna seja exatamente uma seqüência de campos de comprimento fixo idênticos. Para permitir o uso de índices, um tipo de comprimento variável deve possuir a representação interna generalizada usada por array_in e array_out. Por razões históricas (ou seja, claramente errado mas muito tarde para mudar) os índices dos tipos matriz de comprimento fixo começam por zero, em vez de começar por um como nas matrizes de comprimento variável.

Parâmetros

nome

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

nome_do_atributo

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

tipo_de_dado

O nome de um tipo de dado existente que vai se tornar uma coluna do tipo composto.

função_de_entrada

O nome da função que converte os dados da forma textual externa para a forma interna.

função_de_saída

O nome da função que converte os dados da forma interna do tipo para a forma textual externa.

função_de_recepção

O nome da função que converte os dados da forma binária externa do tipo para a forma interna.

função_de_envio

O nome da função que converte os dados da forma interna do tipo para a forma binária externa.

função_de_análise

O nome da função que realiza as análises estatísticas para o tipo de dado.

comprimento_interno

Uma constante numérica que especifica o comprimento em bytes da representação interna do novo tipo. O padrão é assumir como sendo de comprimento variável.

alinhamento

O alinhamento de armazenamento requerido por este tipo de dado. Se for especificado deve ser um entre char, int2, int4 ou double; o padrão é int4.

armazenamento

A estratégia de armazenamento para este tipo de dado. Se for especificado deve ser um entre plain, external, extended ou main; o padrão é plain.

padrão

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

elemento

O tipo sendo criado é uma matriz (array); especifica o tipo dos elementos da matriz.

delimitador

O caractere delimitador a ser usado entre os valores nas matrizes (arrays) feitas deste tipo.

Observações

Os nomes dos tipo definidos pelo usuário não podem começar pelo caractere sublinhado (_), e só podem ter 62 caracteres de comprimento (ou, de modo geral, NAMEDATALEN-2, em vez dos NAMEDATALEN-1 caracteres permitidos para os outros nomes). Os nomes de tipo começados por sublinhado são reservados para os nomes dos tipos matriz criados internamente.

Como não existe restrição para utilizar um tipo de dado após este ter sido criado, a criação de um tipo base equivale a conceder permissão de execução para todos nas funções mencionadas na definição do tipo (portanto, é necessário que o criador do tipo seja o dono destas funções). Isto normalmente não é um problema, devido ao tipo de função que é útil para definição de tipo. Mas é preciso pensar duas vezes antes de projetar um tipo para o qual seja necessário utilizar uma informação "sigilosa" para converter de/para a forma externa.

Nas versões do PostgreSQL anteriores a 8.2 a sintaxe CREATE TYPE nome não existia. A forma de criar o novo tipo base era criando primeiro sua função de entrada. Nesta abordagem, o PostgreSQL vê primeiro o nome do novo tipo de dado como o tipo retornado pela função de entrada. Nesta situação o tipo "invólucro" é criado implicitamente, podendo então ser referenciado na definição das funções de E/S remanescentes. Esta abordagem ainda funciona, mas está em obsolescência podendo ser desativada nas versões futuras. Além disso, para evitar a desorganização acidental dos catálogos com tipos invólucros que são simplesmente o resultado da digitação errada na definição da função, os tipos invólucro só serão construídos desta forma quando a função de entrada estiver escrita em C.

Nas versões do PostgreSQL anteriores a 7.3 era costume evitar a criação do tipo "invólucro", substituindo as referências à frente da função para o nome do tipo pelo pseudotipo guardador de lugar opaque. Os argumentos e resultados cstring também tinham que ser declarados como opaque antes da versão 7.3. Para permitir a carga de cópias de segurança antigas, o comando CREATE TYPE aceita as funções declaradas usando opaque, mas mostra uma mensagem e muda as declarações da função para usar os tipos corretos.

Exemplos

Este exemplo cria um tipo composto e o utiliza na definição de uma 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 o tipo de dado base box e, em seguida, o utiliza na definição da 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 ter sido usado

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

o que permitiria o acesso por índice aos números componentes do valor box. Fora isso, o tipo se comporta do mesmo modo que antes.

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

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

Podem ser encontrados mais exemplos, incluindo funções de entrada e de saída, na Seção 33.11.

Compatibilidade

Este comando CREATE TYPE é uma extensão do PostgreSQL. Existe um comando CREATE TYPE no padrão SQL que é bastante diferente nos detalhes.

Consulte também

CREATE FUNCTION, DROP TYPE, ALTER TYPE, CREATE DOMAIN

Notas

[1]

4.4.1 — Informações gerais sobre tipo de dados — Cada valor de dado pertence a algum tipo de dado. Cada tipo de dado é pré-definido, construído ou definido pelo usuário. Cada tipo de dado possui um nome. O nome de um tipo de dado pré-definido ou construído é uma palavra reservada especificada pela parte do padrão ISO/IEC 9075 que especifica o tipo de dado. O nome do tipo de dado definido pelo usuário é fornecido na sua definição. O tipo de dado definido pelo usuário é um objeto do esquema. O tipo de dado pré-definido é um tipo de dado especificado pelo padrão ISO/IEC 9075 e, portanto, é fornecido pela implementação do SQL. O tipo de dado é pré-definido mesmo que seja requerido (ou permitido) o usuário fornecer certos parâmetros quando o especifica (por exemplo, a precisão do número). O tipo de dado pré-definido é atômico. O tipo atômico é um tipo de dado cujos valores não são compostos de valores de outros tipos de dado. A existência de uma operação (SUBSTRING, EXTRACT) capaz de selecionar parte do valor cadeia de caracteres ou data e hora não implica que a cadeia de caracteres ou a data e hora não sejam atômicos. Um tipo construído é atômico ou composto. O tipo composto é um tipo de dado cujos valores são compostos de zero ou mais valores, cada um de um tipo de dado declarado. (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-1:2003 (E) (N. do T.)

[2]

SQL Server — O comando CREATE TYPE cria um tipo de dado aliás ou um tipo definido pelo usuário em uma instância do SQL Server 2005. SQL Server 2005 Books Online — CREATE TYPE (Transact-SQL) (N. do T.)

[3]

O DB2 também fornece suporte para tipos de dado definidos pelo usuário, que são classificados em três categorias: tipos distintos definidos pelo usuário (UDT), que permitem a criação de um novo tipo de dado, possuindo semântica própria, baseado em um tipo de dado existente; tipos estruturados definidos pelo usuário, que permitem a criação de uma estrutura contendo uma seqüência de atributos nomeados, cada um destes com seu tipo de dado, sendo esta uma das extensões das funções objeto-relacionais do DB2; e tipo referência definido pelo usuário, um tipo companheiro do tipo estruturado definido pelo usuário, que de forma semelhante ao tipo distinto definido pelo usuário é um tipo escalar que compartilha uma representação com um dos tipos de dado nativos, podendo ser usado para fazer referência a linhas em outra tabela que utilizam um tipo estruturado definido pelo usuário. DB2® Universal Database™ V8 for Linux, UNIX, and Windows Database Administration Certification Guide, 5th Edition, George Baklarz e Bill Wong, Series IBM Press, Prentice Hall Professional Technical Reference, 2003, pág. 192. (N. do T.)

[4]

4.6.4.1 — Tipos estruturados — O tipo de dado estruturado é um tipo de dado com nome, definido pelo usuário. O valor do tipo estruturado é composto por um número fixo de valores de atributo. Cada atributo do tipo estruturado possui um tipo de dado, especificado pelo tipo do atributo que está incluído no descritor do tipo estruturado.

4.6.4.2 — Atributos — O atributo é um componente com nome do tipo estruturado. O atributo possui tipo de dado e valor padrão. (ISO-ANSI Working Draft) Framework (SQL/Framework), August 2003, ISO/IEC JTC 1/SC 32, 25-jul-2003, ISO/IEC 9075-1:2003 (E) (N. do T.)

[5]

O SQL Server 2000 também suporta o tipo de dado base tabela, que pode ser utilizado para armazenar o conjunto de resultados de um comando SQL. O tipo de dado tabela não pode ser utilizado para colunas de tabela, somente pode ser utilizado nas variáveis do Transact-SQL e nos valores retornados pelas funções definidas pelo usuário. Data Types and Table Structures (N. do T.)

[6]

DB2 — O comando CREATE TYPE define um tipo estruturado definido pelo usuário. O tipo estruturado definido pelo usuário pode incluir zero ou mais atributos. O tipo estruturado pode ser um subtipo, permitindo os atributos serem herdados de um supertipo. A execução bem-sucedida deste comando gera métodos para ler e atualizar os valores dos atributos. A execução bem-sucedida deste comando também gera funções para construir instâncias do tipo estruturado utilizado em uma coluna, para converter entre o tipo de referência e seu tipo de representação, e para dar suporte aos operadores de comparação (=, <>, <, <=, >, e >=) no tipo de referência. DB2 Version 9 for Linux, UNIX, and Windows (N. do T.)

SourceForge.net Logo CSS válido!