Capítulo 5. Tipos de dado

Índice
5.1. Tipos numéricos
5.1.1. Os tipos inteiros
5.1.2. Números de precisão arbitrária
5.1.3. Tipos de ponto flutuante
5.1.4. Os tipos seriais
5.2. Tipo monetário
5.3. Tipos para caracteres
5.4. Tipo para cadeias binárias
5.5. Tipos para data e hora
5.5.1. Entrada de data e hora
5.5.2. Saídas de data e hora
5.5.3. Zonas horárias
5.5.4. Internals
5.6. Tipo booleano
5.7. Tipos geométricos
5.7.1. Ponto
5.7.2. Segmento de linha
5.7.3. Caixa
5.7.4. Caminho
5.7.5. Polígono
5.7.6. Círculo
5.8. Tipos de dado para endereço de rede
5.8.1. inet
5.8.2. cidr
5.8.3. inet vs cidr
5.8.4. macaddr
5.9. Tipos para cadeias de bits
5.10. Tipos identificadores de objetos
5.11. Pseudotipos
5.12. Matrizes

O PostgreSQL disponibiliza para os usuários um amplo conjunto de tipos de dado nativos. Os usuários podem adicionar novos tipos ao PostgreSQL utilizando o comando CREATE TYPE.

A Tabela 5-1 mostra todos os tipos de dado de propósito geral incluídos na distribuição padrão. A maioria dos nomes alternativos listados na coluna "Aliases" é o nome utilizado internamente pelo PostgreSQL por motivos históricos. Além desses, existem alguns tipos usados internamente ou obsoletos não mostrados aqui.

Tabela 5-1. Tipos de dado

Nome do tipoAliasesDescrição
bigintint8inteiro de oito bytes com sinal
bigserialserial8inteiro de oito bytes autoincremental
bit cadeia de bits de comprimento fixo
bit varying(n)varbit(n)cadeia de bits de comprimento variável
booleanboolbooleano lógico (verdade/falso)
box caixa retangular em plano 2D
bytea dados binários
character varying(n)varchar(n)cadeia de caracteres de comprimento variável
character(n)char(n)cadeia de caracteres de comprimento fixo
cidr endereço de rede IP
circle círculo em plano 2D
date data de calendário (ano, mês,dia)
double precisionfloat8número de ponto flutuante de precisão dupla
inet endereço de hospedeiro IP
integerint, int4inteiro de quatro bytes com sinal
interval(p) intervalo de tempo de uso geral
line linha infinita em plano 2D (não implementado)
lseg segmento de linha em plano 2D
macaddr endereço MAC
money valor monetário
numeric [ (p, s) ]decimal [ (p, s) ]numérico exato com precisão selecionável
path caminho geométrico aberto e fechado em plano 2D
point ponto geométrico em plano 2D
polygon caminho geométrico fechado em plano 2D
realfloat4número de ponto flutuante de precisão simples
smallintint2inteiro de dois bytes com sinal
serialserial4inteiro de quatro bytes autoincremental
text cadeia de caracteres de comprimento variável
time [ (p) ] [ without time zone ] hora do dia
time [ (p) ] with time zonetimetzhora do dia, incluindo a zona horária
timestamp [ (p) ] without time zonetimestampdata e hora
timestamp [ (p) ] [ with time zone ]timestamptzdata e hora, incluindo a zona horária

Compatibilidade: Os seguintes tipos são especificados pelo SQL: bit, bit varying, boolean, char, character varying, character, varchar, date, double precision, integer, interval, numeric, decimal, real, smallint, time, timestamp (ambos com ou sem zona horária).

Cada tipo de dado possui uma representação externa determinada pelas suas funções de entrada e de saída. Muitos tipos nativos possuem um formato externo óbvio. Entretanto, muitos tipos são exclusivos do PostgreSQL, como caminhos abertos e fechados, ou possuem formatos com várias possibilidades, como os tipos de data e hora. A maioria das funções de entrada e de saída correspondentes aos tipos básicos (por exemplo, números inteiros e de ponto flutuante) executa alguma verificação de erro. Algumas das funções de entrada e saída não são inversíveis, ou seja, o resultado da função de saída pode perder precisão quando comparado com a entrada original.

Para melhorar o tempo de execução, alguns operadores e funções (por exemplo, adição e multiplicação) não realizam verificação de erro em tempo de execução. Por isso, em alguns sistemas os operadores numéricos para alguns tipos de dado podem estourar a capacidade sem avisar.

5.1. Tipos numéricos

Os tipos numéricos consistem de inteiros de dois, quatro e oito bytes, números de ponto flutuante de quatro e oito bytes, e decimais de precisão fixa. A Tabela 5-2 lista os tipos disponíveis.

Tabela 5-2. Tipos numéricos

Nome do tipoTamanho de armazenamentoDescriçãoFaixa de valores
smallint2 bytesprecisão fixa com faixa pequena-32768 a +32767
integer4 bytesescolha usual para precisão fixa-2147483648 a +2147483647
bigint8 bytesprecisão fixa com faixa grande-9223372036854775808 a 9223372036854775807
decimalvariávelprecisão especificada pelo usuário, exatosem limite
numericvariávelprecisão especificada pelo usuário, exatosem limite
real4 bytesprecisão variável, inexatoprecisão de 6 dígitos decimais
double precision8 bytesprecisão variável, inexatoprecisão de 15 dígitos decimais
serial4 bytesinteiro autoincremental1 a 2147483647
bigserial8 bytesinteiro autoincremental grande1 a 9223372036854775807

A sintaxe das constantes especificando tipos numéricos é descrita na Seção 1.1.2. Os tipos numéricos possuem um conjunto completo de operadores aritméticos e funções correspondentes. Consulte o Capítulo 6 para obter mais informação. As próximas seções descrevem os tipos em detalhe.

5.1.1. Os tipos inteiros

Os tipos smallint, integer e bigint armazenam números inteiros, ou seja, números sem a parte fracionária, com diferentes faixas de valor. A tentativa de armazenar um valor fora da faixa permitida ocasiona erro.

O tipo integer é a escolha usual, porque oferece o melhor equilíbrio entre faixa de valores, tamanho de armazenamento e desempenho. Geralmente o tipo smallint só é utilizado quando o espaço em disco está muito escasso. O tipo bigint somente deve ser usado quando a faixa de valores de integer não for suficiente, porque este último é bem mais rápido.

O tipo bigint pode não funcionar de modo correto em todas as plataformas, porque depende de suporte no compilador para inteiros de oito bytes. Nas máquinas sem este suporte, o bigint age do mesmo modo que o integer (mas ainda demanda oito bytes para seu armazenamento). Entretanto, não é de nosso conhecimento nenhuma plataforma razoável onde este caso ainda se aplique.

O padrão SQL somente especifica os tipos inteiros integer (ou int) e smallint. O tipo bigint, e os nomes de tipo int2, int4 e int8 são extensões, também compartilhadas por vários outros sistemas de banco de dados SQL.

Nota: Havendo uma coluna do tipo smallint ou bigint com um índice, podem ocorrer problemas ao tentar fazer o sistema utilizar este índice. Por exemplo, uma cláusula do tipo

... WHERE coluna_smallint = 42

não usará o índice, porque o sistema atribui o tipo integer à constante 42, e o PostgreSQL atualmente não pode utilizar um índice quando dois tipos de dado diferentes estão envolvidos. Um modo de contornar este problema é colocar a constante entre apóstrofos. Portanto,

... WHERE coluna_smallint = '42'

atrasa a resolução do tipo pelo sistema, fazendo com que seja atribuído o tipo correto para a constante.

5.1.2. Números de precisão arbitrária

O tipo numeric pode armazenar números com até 1.000 dígitos de precisão realizando cálculos exatos, sendo recomendado, especialmente, para armazenar quantias monetárias e outras quantidades onde a exatidão é requerida. Entretanto, o tipo numeric é muito lento quando comparado com os tipos de ponto flutuante descritos na próxima seção.

Os seguintes termos são utilizados : A escala do tipo numeric é o número de dígitos decimais da parte fracionária, à direita do ponto decimal. A precisão do tipo numeric é o número total de dígitos significativos em todo o número, ou seja, o número de dígitos nos dois lados do ponto decimal. Portanto, o número 23.5141 [1] possui precisão igual a 6 e escala igual a 4. Os inteiros podem ser considerados como tendo escala igual a zero.

Tanto a precisão quanto a escala do tipo numérico podem ser configuradas. Para declarar a coluna como sendo do tipo numeric deve ser utilizada a sintaxe:

NUMERIC(precisão, escala)

A precisão deve ser um número positivo, enquanto a escala pode ser zero ou positiva. Como forma alternativa,

NUMERIC(precisão)

especifica escala igual a 0. Especificando-se

NUMERIC

sem qualquer precisão ou escala é criada uma coluna onde os valores numéricos com qualquer precisão ou escala podem ser armazenados, até a precisão limite da implementação. Uma coluna deste tipo não transforma os valores de entrada para nenhuma determinada escala, enquanto as colunas do tipo numeric com escala declarada transformam os valores da entrada para esta escala (O padrão SQL requer a escala padrão sendo igual a 0, ou seja, uma transformação para a precisão inteira. Consideramos isto sem utilidade. Havendo preocupação com a portabilidade, sempre deve ser especificada explicitamente a precisão e a escala).

Se a precisão ou a escala do valor for maior que a precisão ou a escala declarada para a coluna, o sistema tenta arredondar o valor. Se o valor não puder ser arredondado para satisfazer os limites declarados, ocasiona erro.

Os tipos decimal e numeric são equivalentes. Os dois tipos fazem parte do padrão SQL.

5.1.3. Tipos de ponto flutuante

Os tipos de dado real e double precision são tipos numéricos de precisão variável não exatos. Na prática, estes tipos são geralmente implementações do padrão IEEE 754 para aritmética binária de ponto flutuante de precisão simples e dupla, respectivamente, conforme suportado pelo processador, sistema operacional e compilador utilizados.

Não exato significa que alguns valores não podem ser convertidos exatamente para o formato interno, sendo armazenados como aproximações. Portanto, ao armazenar e imprimir um valor podem ocorrer pequenas discrepâncias. A gerência destes erros, e como se propagam através dos cálculos, é assunto de um ramo da ciência da computação e da matemática que não será discutido aqui, com exceção dos seguintes pontos:

  • Se o armazenamento e cálculos exatos (tal como em valores monetários) forem necessários, deve ser utilizado o tipo numeric em vez destes.

  • Se cálculos complicados forem efetuados com estes tipos para algo importante, especialmente se depender de certos comportamentos em situações limites (infinito, underflow), a implementação deve ser avaliada cuidadosamente.

  • A comparação de igualdade de dois valores de ponto flutuante pode funcionar conforme o esperado, ou não.

Normalmente o tipo real possui uma faixa de pelo menos -1E+37 a +1E+37, com uma precisão de pelo menos 6 dígitos decimais. O tipo double precision normalmente possui uma faixa em torno de -1E+308 a +1E+308 com uma precisão de pelo menos 15 dígitos. Os valores muito pequenos ou muito grandes causam erro. O arredondamento pode ser efetuado se a precisão do número entrado for muito grande. Os números muito próximos de zero, que não podem ser representados de forma diferente de zero, causam erro de underflow.

5.1.4. Os tipos seriais

O tipo de dado serial não é na verdade um tipo, mas meramente uma notação conveniente para especificar colunas identificadoras (semelhante à propriedade AUTO_INCREMENT existente em alguns outros bancos de dados). Na implementação corrente especificar

CREATE TABLE nome_tabela (
    nome_coluna SERIAL
);

é o mesmo que especificar:

CREATE SEQUENCE nome_tabela_nome_coluna_seq;
CREATE TABLE nome_tabela (
    nome_coluna integer DEFAULT nextval('nome_tabela_nome_coluna_seq') NOT NULL
);

Conforme visto, foi criada uma coluna do tipo inteiro e feito o valor padrão ser atribuído a partir de um gerador de seqüência. A restrição NOT NULL foi aplicada para garantir que o valor nulo não pode ser inserido explicitamente. Na maioria das vezes, deve ser colocada uma restrição UNIQUE ou PRIMARY KEY para não permitir a inserção de valores duplicados por acidente, mas isto não é automático.

A utilização da coluna serial para inserir o próximo valor da seqüência na tabela é feita atribuindo o valor padrão da coluna serial. Pode ser feito omitindo a coluna da lista de colunas do comando INSERT, ou por meio da utilização da palavra chave DEFAULT.

Os nomes de tipo serial e serial4 são equivalentes: os dois criam uma coluna do tipo integer. Os nomes de tipo bigserial e serial8 funcionam do mesmo modo, exceto por criarem uma coluna do tipo bigint. O tipo bigserial deve ser utilizado se forem esperados mais que 231 identificadores durante a existência da tabela.

A seqüência criada pelo tipo serial é automaticamente excluída quando a coluna onde foi definida é excluída, e não pode ser excluída de outra forma (Isto não era verdade no PostgreSQL antes da versão 7.3. Observe que esta ligação de exclusão automática não ocorre para uma seqüência criada pela restauração da cópia de segurança de um banco de dados pré-7.3; a cópia de segurança não contém as informações necessárias para estabelecer a ligação de dependência). Além disso, a dependência entre a seqüência e a coluna é feita apenas para a própria coluna serial; se qualquer outra coluna fizer referência à seqüência (talvez chamando manualmente a função nextval()), pode haver quebra se a seqüência for removida. A utilização de colunas serial como costume é considerado um estilo ruim.

Nota: Antes do PostgreSQL 7.3 serial implicava UNIQUE. Isto não é mais automático. Se for desejado que uma coluna serial também seja UNIQUE ou PRIMARY KEY, deve ser especificado da mesma forma como é feito para qualquer outro tipo.

Notas

[1]

Padrão americano, ponto e não vírgula separando a parte fracionária. (N.T.)