• Nenhum resultado encontrado

Tipos compostos

No documento Documentação do PostgreSQL 8.0.0 (páginas 133-136)

Tipos de junção

Capítulo 8. Tipos de dado

8.11. Tipos compostos

1 | 6 (1 linha)

Conforme mostrado anteriormente, ao escrever um valor matriz pode-se colocar aspas em torno de qualquer elemento individual da matriz. Isto deve ser feito se o valor do elemento puder, de alguma forma, confundir o analisador de valor matriz. Por exemplo, os elementos contendo chaves, vírgulas (ou qualquer que seja o caractere delimitador), aspas, contrabarras ou espaços em branco na frente ou atrás devem estar entre aspas. Para colocar aspas ou contrabarras no valor entre aspas do elemento da matriz, estes devem ser precedidos por uma contrabarra. Como alternativa, pode ser utilizado o escape de contrabarra para proteger qualquer caractere de dado que seria de outra forma considerado como sintaxe da matriz.

Podem ser escritos espaços em branco antes do abre chaves ou após o fecha chaves. Também podem ser escritos espaços em branco antes ou depois de qualquer item individual cadeia de caracteres. Em todos estes casos os espaços em branco são ignorado. Entretanto, espaços em branco dentro de elementos entre aspas, ou envoltos nos dois lados por caracteres de um elemento que não são espaços em branco, não são ignorados.

Nota: Lembre-se que o que se escreve em um comando SQL é interpretado primeiro como um literal cadeia de caracteres e, depois, como uma matriz. Isto duplica o número de contrabarras necessárias. Por exemplo, para inserir um valor matriz do tipo text contendo uma contrabarra e uma aspa, deve ser escrito

INSERT ... VALUES ('{"\\\\","\\""}');

O processador de literais cadeias de caracteres remove um nível de contrabarras, portanto o que chega para o analisador de valor matriz se parece com {"\\","\""}. Por sua vez, as cadeias de caracteres introduzidas na rotina de entrada do tipo de dado text se tornam \ e ", respectivamente (Se estivéssemos trabalhando com um tipo de dado cuja rotina de entrada também tratasse as contrabarras de forma especial como, por exemplo, bytea, seriam necessárias oito contrabarras no comando para obter uma contrabarra armazenada no elemento da matriz). Pode ser utilizada a delimitação por cifrão (dollar quoting) (consulte a Seção 4.1.2.2) para evitar a necessidade de duplicar as contrabarras.

Dica: Ao se escrever valores matrizes nos comandos SQL, geralmente é mais fácil trabalhar com a sintaxe do construtor de ARRAY (consulte a Seção 4.2.10) do que com a sintaxe do literal cadeia de caracteres. Em ARRAY, os valores dos elementos individuais são escritos da mesma maneira como seriam escritos caso não fossem membros de uma matriz.

8.11. Tipos compostos

O tipo composto descreve a estrutura de uma linha ou registro; essencialmente, é apenas uma lista de nomes de campos com seus tipos de dado. O PostgreSQL permite que os valores de tipo composto sejam utilizados de muitas maneiras idênticas às que os tipos simples podem ser ser utilizados. Por exemplo, uma coluna de uma tabela pode ser declarada como sendo de um tipo composto.

8.11.1. Declaração de tipos compostos

Abaixo seguem dois exemplos simples definindo tipos compostos:

CREATE TYPE complexo AS ( r double precision, i double precision );

CREATE TYPE catalogo AS ( nome text, id_fornecedor integer, preco numeric );

A sintaxe pode ser comparada a do comando CREATE TABLE, exceto que somente podem ser especificados os nomes e tipos dos campos; atualmente não pode ser incluída nenhuma restrição (como NOT NULL). Deve ser observado que a

palavra chave AS é essencial; sem esta, o sistema imagina que está lidando com um tipo bem diferente de comando CREATE TYPE, e mostra erros de sintaxe bem estranhos.

Após definir os tipos, estes podem ser utilizados para criar tabelas:

CREATE TABLE estoque ( item catalogo, contador integer );

INSERT INTO estoque VALUES (ROW('dados de pano', 42, 1.99), 1000);

ou funções:

CREATE FUNCTION preco_quantidade(catalogo, integer) RETURNS numeric AS 'SELECT $1.preco * $2' LANGUAGE SQL;

SELECT preco_quantidade(item, 10) FROM estoque;

Sempre que uma tabela é criada também é criado, automaticamente, um tipo composto com o mesmo nome da tabela para representar o tipo linha da tabela. 21 Por exemplo, se tivéssemos declarado

CREATE TABLE catalogo ( nome text,

id_fornecedor integer REFERENCES fornecedores, preco numeric CHECK (preco > 0)

);

teria sido criado como subproduto o mesmo tipo composto catalogo mostrado acima, podendo ser utilizado conforme mostrado anteriormente. Entretanto, deve ser observada uma restrição importante da implementação corrente: uma vez que não há nenhuma restrição associada ao tipo composto, a restrição mostrada na definição da tabela não se aplica aos valores do tipo composto fora da tabela (Uma forma parcial de evitar este problema é utilizar tipos domínios como membros dos tipos compostos).

8.11.2. Entrada de valor composto

Para escrever um valor composto como uma constante literal, os valores do campo devem ser envoltos por parênteses e separados por vírgulas. Podem ser colocadas aspas em torno de qualquer valor do campo, sendo obrigatório se o valor contiver vírgulas ou parênteses (Abaixo são mostrados mais detalhes). Portanto, o formato geral de uma constante composta é o seguinte:

'( val1 , val2 , ... )' Por exemplo,

'("dados de pano",42,1.99)'

é um valor válido para o tipo catalogo definido acima. Para tornar o campo nulo, não deve ser escrito nenhum caractere na sua posição na lista. Por exemplo, esta constante especifica um terceiro campo nulo:

'("dados de pano",42,)'

Se, em vez de nulo, for desejada uma cadeia de caracteres vazia, devem ser escritas duas aspas:

'("",42,)'

Neste caso, o primeiro campo é uma cadeia de caracteres vazia não-nula, e o terceiro campo é nulo.

(Estas constantes são, na verdade, apenas um caso especial do tipo genérico de constantes mostrado na Seção 4.1.2.5.

Inicialmente, a constante é tratada como uma cadeia de caracteres e passada para a rotina de conversão de entrada de tipo composto (Pode ser necessária uma especificação explícita do tipo).

Também pode ser utilizada a sintaxe da expressão ROW para construir valores compostos. Na maioria dos casos, esta sintaxe é bem mais simples que a sintaxe do literal cadeia de caracteres, uma vez que não é necessário se preocupar com várias camadas de aspas. Este método já foi utilizado acima:

ROW('dados de pano', 42, 1.99) ROW('', 42, NULL)

Desde que haja mais de um campo na expressão, a palavra chave ROW se torna opcional, permitindo simplificar como:

('dados de pano', 42, 1.99) ('', 42, NULL)

A sintaxe da expressão ROW é mostrada com mais detalhes na Seção 4.2.11.

8.11.3. Acesso aos tipos compostos

Para acessar um campo de uma coluna composta deve ser escrito um ponto e o nome do campo, como se faz ao selecionar um campo de uma tabela. Na verdade, é tão parecido com selecionar um campo de uma tabela que, geralmente, é necessário utilizar parênteses para não confundir o analisador. Por exemplo, selecionar alguns subcampos da tabela exemplo estoque usando algo como

SELECT item.nome FROM estoque WHERE item.preco > 9.99;

não funciona, porque o nome item é assumido como sendo o nome da tabela, e não o nome do campo, pelas regras de sintaxe do SQL. Devendo, então, ser escrito como mostrado abaixo

SELECT (item).nome FROM estoque WHERE (item).preco > 9.99;

ou desta forma, se também for necessário utilizar o nome da tabela (por exemplo, numa consulta com várias tabela):

SELECT (estoque.item).nome FROM estoque WHERE (estoque.item).preco > 9.99;

Agora, como o objeto entre parênteses é interpretado corretamente como uma referência à coluna item, é possível selecionar um subcampo da mesma.

Ocorrem problemas de sintaxe semelhantes sempre que é selecionado um campo de um valor composto. Por exemplo, para selecionar apenas um campo do resultado de uma função que retorna um valor composto, é necessário escrever algo como:

SELECT (minha_funcao(...)).campo FROM ...

Sem os parênteses extra, provoca um erro de sintaxe.

8.11.4. Modificação de tipos compostos

Abaixo estão mostrados alguns exemplos da sintaxe apropriada para inserir e atualizar colunas compostas. Primeiro, são inseridas e atualizadas colunas inteiras:

INSERT INTO minha_tabela (coluna_complexa) VALUES((1.1,2.2));

UPDATE minha_tabela SET coluna_complexa = ROW(1.1,2.2) WHERE ...;

O primeiro exemplo omite ROW, enquanto o segundo exemplo não; pode ser feito de qualquer uma destas maneiras.

Os subcampos de uma coluna composta podem ser atualizados individualmente:

UPDATE minha_tabela SET coluna_complexa.r = (coluna_complexa).r + 1 WHERE ...;

Deve ser observado que não é necessário (e, na verdade, não se pode) colocar parênteses em torno do nome da coluna que aparece logo após a cláusula SET, mas são necessários parênteses ao se fazer referência à mesma coluna na expressão à direita do sinal de igual.

Também podem ser especificados subcampos como destino do INSERT:

INSERT INTO minha_tabela (coluna_complexa.r, coluna_complexa.i) VALUES(1.1, 2.2);

Caso não tivéssemos fornecido valores para todos os subcampos da coluna, os demais subcampos seriam preenchidos com o valor nulo.

8.11.5. Sintaxe de entrada e saída dos tipos compostos

A representação textual externa do valor composto é formada por itens que são interpretados de acordo com as regras individuais de conversão de entrada e saída do tipo de dado do campo, mais os adornos que indicam a estrutura composta.

Os adornos são formados por parênteses (( e )) em torno de todo o valor, mais vírgulas (,) entre itens adjacentes. Os espaços em branco fora dos parênteses são ignorados, mas dentro dos parênteses são considerados parte do valor do campo, podendo ou não serem significativos dependendo das regras de conversão de entrada para o tipo de dado do campo. Por exemplo, em

'( 42)'

o espaço em branco é ignorado se o tipo do campo for inteiro, mas não é ignorado se o tipo do campo for texto.

Como mostrado anteriormente, ao se escrever um valor composto podem ser escritas aspas envolvendo qualquer valor individual de campo. Isto deve ser feito se o valor do campo puder, de alguma forma, confundir o analisador de valores compostos. Em particular, os campos contendo parênteses, vírgulas, aspas ou contrabarras devem estar entre aspas (Além disso, um par de aspas dentro de um valor de campo envolto por aspas é assumido como representando o caractere aspas, de maneira análoga à regra para os apóstrofos nas cadeias de caracteres literais do SQL). Como alternativa, pode ser utilizado o escape de contrabarra para proteger todos os caracteres dos dados que, de outra forma, seriam assumidos como fazendo parte da sintaxe do tipo composto.

Um valor de campo inteiramente vazio (nenhum caractere entre as vírgulas ou parênteses) representa o valor nulo. Para escrever um valor que seja uma cadeia de caracteres vazia, e não o valor nulo, deve ser escrito "".

A rotina de saída do tipo composto coloca aspas em torno dos valores dos campos caso estes sejam cadeias de caracteres vazias, ou contenham parêntese, vírgulas, aspas, contrabarras ou espaços em branco (Fazer isto para os espaços em branco não é essencial, mas melhora a legibilidade). Aspas e contrabarras incorporadas aos valores dos campos são duplicadas.

Nota: Deve ser lembrado que, o que se escreve em um comando SQL, é interpretado primeiro como um literal cadeia de caracteres e, depois, como um tipo composto. Isto duplica o número de contrabarras necessárias. Por exemplo, para inserir um campo do tipo text contendo uma contrabarra e uma aspas em um valor composto, deve ser escrito:

INSERT ... VALUES ('("\\"\\\\")');

O processador de literais cadeias de caracteres remove um nível de contrabarras, portanto o que chega ao analisador de valor composto se parece com ("\"\\"). Por sua vez, a cadeia de caracteres introduzida na rotina de entrada do tipo de dado text se torna "\ (Se estivéssemos trabalhando com um tipo de dado cuja rotina de entrada também tratasse as contrabarras de forma especial como, por exemplo, bytea, seriam necessárias oito contrabarras no comando para obter uma contrabarra armazenada no campo composto). Pode ser utilizada a delimitação por cifrão (dollar quoting) (consulte a Seção 4.1.2.2) para evitar a necessidade de duplicar as contrabarras.

Dica: Ao se escrever valores compostos nos comandos SQL, normalmente é mais fácil trabalhar com a sintaxe do construtor ROW do que com a sintaxe do literal composto. Usando ROW os valores individuais dos campos são escritos da mesma maneira como seriam escritos se não fossem membros de um valor composto.

No documento Documentação do PostgreSQL 8.0.0 (páginas 133-136)