AE    
Por A. Elein Mustain
Traduzidos por Juliano da Silva Ignacio
General Bits 2-Jun-2003 Edição: 28

General Bits é uma coluna baseada na lista de discussão do PostgreSQL pgsql-general.
Para saber mais sobre a lista de discussão pgsql-general e sobre o PostgreSQL, procure em http://www.postgresql.org/.
Arquivos
General Tidbits
Artigos Português
Google General Bits
Notícias
Para receber um aviso via email sobre as novas edições do General Bits, envie um email para Elein.
ae Consulting PostgreSQL Design & Implementation
Assinaturas Support General Bits
pghostger.com
OSCON Speaker
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Mais uma vez: o que o NULL não é
[GENERAL] Consultas às quais não foram postadas para a lista de NULLS, sendo aqui listadas 27/Mai/2003

Contrariamente ao que o Oracle e outros sistemas de bancos de dados menos conhecidos dizem, uma string vazia, '', não é a mesma coisa do que NULL. Se você está habituado com outros sistemas, pode ser fácil cometer erros no entanto. Então, se você achar que está selecionando registros com valores NULL nas colunas que você não espera vê-lo, talvez esteja tendo problemas com strings vazias no lugar de NULLs.

Você precisará prestar atenção na fonte de dados para prevenir futuros dados inválidos, achar os registros problemáticos, corrigí-los e então, escrever no quadro negro 100 vezes "NULL é diferente de uma string vazia" :-)

Para ver se um valor é NULL ou uma string vazia, as pessoas enviaram um número razoável de consultas interessantes. As diversas formas que as pessoas escolhem para testar sobre o que há em uma coluna foi surpreendente. Alguns testam se é NULL, alguns se não é NULL, alguns por strings vazias, alguns por strings que não estão vazias e alguns através de uma operação sobre a coluna. Algumas destas consultas são melhores do que outras para esta tarefa. Eu mesmo prefiro usar a opção coalesce(). Mas cada seleção mostra uma maneira diferente de visualizar o problema e isto é muito interessante. Aqui estão algumas delas.

    -- Se você consultar um registro onde a coluna jobcomment não é nula, então 
    -- provavelmente há uma string vazia nela ...
	SELECT jobcomment 
	FROM tblJobIncharge 
	WHERE id=51 AND jobcomment IS NOT NULL;

    -- Para ter certeza que a coluna jobcomment não é [uma string vazia] você pode tentar esta consulta:
    -- Se jobcomment é uma string vazia então irá retornar um '0' no campo de comentários do serviço,
    -- Se estiver realmente null então não retornará nada
	SELECT jassignedid, ascii(JobComments) 
	FROM tblJobIncharge 
	WHERE JobComments IS NOT NULL AND projectid >= 50 AND projectid <= 100

    -- Qualquer resultado nesta coluna que for null, será mostrado um 'X' ao invés de nada.
	SELECT jassignedid, coalesce(JobComments,'X') 
	FROM tblJobIncharge
	WHERE JobComments IS NOT NULL AND projectid >= 50 AND projectid <= 100


    -- Neste caso não somente irá mostrar a você onde há realmente valores null (já que null 
    -- em uma operação || retorna null) mas também indica a string entre 'xx' e 'xx'.
	SELECT jassignedid, 'xx' || JobComments || 'xx'
	FROM tblJobIncharge
	WHERE projectid >= 50 AND projectid <= 100


    -- O tamanho da coluna irá dizer quantos espaços (ou caracteres) há, se houver algum.
	SELECT jassignedid, JobComments, length(JobComments)
	FROM tblJobIncharge
	WHERE JobComments IS NOT NULL
	AND projectid >= 50 AND projectid <= 100;

Não se esqueça de verificar suas origens de dados por semânticas perdidas. Por exemplo, aplicações baseadas em formulários irão submeter strings vazias às quais podem ser criadas para serem interpretadas como NULL. No PostgreQSL este é um jeito de como você poderia atualizar o dado baseado em uma entrada em branco.

	UPDATE tblJobIncharge
	SET JobComments = NULL
	WHERE LENGTH(RTRIM(JobComments)) = 0;

Colaboradores: shreedhar shreedhar em lucidindia.net, Jean-Christian Imbeault jc em mega-bucks.co.jp, Nigel J. Andrews nandrews em investsystems.co.uk, Vincent Hikida vhikida em inreach.com, Andrew Sullivan andrew em libertyrms.info

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Views e Funções que Retornam Registros
[GENERAL] as views estão obsoletas ? 19/Mai/2003

Este questionamento foi levantado caso as views se tornassem "obsoletas" com o advento das funções que retornam conjuntos de dados (SRF - Set Returning Functions). (na verdade a questão é sobre as funções que retornam conjuntos de registros - FRSR, functions returning sets of rows - que são um subconjunto dos SRFs :-) (Veja a Edição #26 para informações sobre funções que retornam conjuntos de dados, funções que retornam registros e funções que retornam conjuntos de registros.)

A view não irá se tornar obsoleta com relação ao FRSR por diversas razões. A primeira delas é que as views já são conhecidas e muito utilizadas. Elas são fáceis de construir. As pessoas estão somente aprendendo a construir FRSRs e isto não é nada mais que um novo recurso. Este recurso é extremamente útil mas se uma view fosse adequada no caso, a view pode e deve ser usada considerando sua simplicidade, caso não haja uma outra razão.

Mas há uma outra razão. A otimização do SQL no PostgreSQL é muito boa. E o planner (programa de pranejamento de execução das instruções em SQL) pode otimizar as views por causa simplicidade da definição do SQL. O planner, no entanto, não pode otimizar funções. Funções não são claras para o planner e podem resultar em inúmeras variações que, dessa maneira, ele não consegue determinar precisamente o plano.

Funções em SQL também não são otimizadas. No entanto, poderia ser possível no futuro, que funções em SQL possam ser trazidas automaticamente para dentro das chamadas de instruções SQL e, otimizadas com o resto da instrução. Isto não está implementado no momento.

Colaboradores: Karsten Hilbert Karsten.Hilbert em gmx.net, Tom Lane tgl em sss.pgh.pa.us, Gianni Mariani gianni em mariani.ws, elein em varlena.com


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Posição do cursor após uma busca
[GENERAL] FETCH ALL posiciona o cursor de forma estranha? 08/Mai/2003

Quando usar CURSORes você precisa saber onde o CURSOR está após fazer um FETCH.

A sintaxe de FETCH é:
	FETCH [direção] [número de registros] { FROM | IN } nome do cursor
A primeira regra é que o cursor está posicionado no último registro retornado. Se o cursor está no ROW[n] (enésimo registro), então a busca relativa começa à partir do próximo registro, ROW[n+1]. A exceção à regra é quando você trabalha com FETCH ALL. Esta instrução posiciona o cursor uma linha após o ÚLTIMO registro retornado, já preparado para executar uma busca reversa.

INSTRUÇÃO REGISTRO
[0] [1] ... [n-1] [n] [n+1] ... [ÚLTIMO] [ÚLTIMO+1]
FETCH 1 FROM cursor       início fim      
FETCH - 1 FROM cursor     fim início        
FETCH #rows FROM cursor             fim  
FETCH ALL FROM cursor               fim

Colaboradores: Bill Gribble grib em linuxdevel.com, Tom Lane tgl em sss.pgh.pa.us

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Restrições em Elementos de um Vetor
[GENERAL] Ajuda em restrições com vetor 03/Abr/2003

Uma coluna com um tipo vetor (array), às vezes necessita de restrições (constraints). Em geral, não é possível criar uma restrição em elementos individuais de um vetor, exceto utilizando uma função como restrição.

No caso deste exemplo, os elementos do vetor letters devem estar na coluna id da tabela lettervals. Esta foi a primeira tentativa. Isto NÃO funcionará:

	create table foo (
		letters	char(1)[3] REFERENCES lettervals(id)
		...
Isto não funciona porque está tentando referenciar o valor de um vetor completo para um único valor de letter. Um vetor completo e um valor único de letter não são o mesmo tipo.

Nigel Andrews sugeriu a seguinte função utilizando-a como trigger. Esta função percorre todo o vetor e verifica se o elemento do vetor está na tabela lettervals (na coluna id). Caso não esteja, um erro é criado abortando o INSERT.

	CREATE FUNCTION letter_fk () RETURNS TRIGGER AS '
	DECLARE
		ind	integer;
	BEGIN
		FOR ind IN array_dims(NEW.letters) LOOP
			PERFORM 1 FROM lettervals WHERE id = NEW.letters[ind];
			IF NOT FOUND THEN
				RAISE EXCEPTION
					''Violação da minha restrição de chave estrangeira'';
			END IF;
		END LOOP;
		RETURN NEW;
	END;
	' AS LANGUAGE 'plpgsql';

	CREATE TRIGGER lettercheck BEFORE INSERT ON foo
	FOR EACH row
	EXECUTE PROCEDURE letter_fk();

Joe Conway nos lembra que ele está trabalhando numa atualização considerável à suporte de vetores para a versão 7.4, à qual irá mover algumas das funcionalidades de vetores encontradas em contrib para o código base do PostgreSQL. Nós temos visto algumas das suas funções em edições anteriores do General Bits tratando de arrays e buscando a sua inserção na versão 7.4.

Colaboradores: Jason Hihn jhihn em paytimepayroll.com, Antti Haapala antti.haapala em iki.fi, Richard Huxton dev em archonet.com, Nigel J. Andrews nandrews em investsystems.co.uk, Joe Conway mail em joeconway.com, Stephan Szabo sszabo em megazone23.bigpanda.com

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Carregando Dados Duvidosos
[GENERAL] interrupção implícita prejudica? 24/Mai/2003

Quando temos que carregar um volume muito grande de dados, às vezes, estes dados estão ruins e a transação inteira é interrompida (ou abortada) deixando você com todos os dados não processados por ir. Isto pode ser um tanto quanto frustrante. Não é fácil ignorar restrições na tabela. A alternativa é usar um script e inserir cada registro separadamente com autocommit ligado. Isto deixará os dados confiáveis entrar e você pode armazear os registros "ruins" para limpá-los (ou tratá-los) mais tarde.

Uma outra sugestão de tratar isto veio de Jan Wieck. Ele sugeriu carregar em uma "staging table" (tabela de preparação) à qual irá conter as mesmas características da tabela de destino, mas sem as restrições e referências. Com esta tabela de preparação você pode consultar dados os quais não combinariam com as restrições, você irá querer reforçar os dados quando necessários, poderá corrigí-los ou remover os registros. Uma vez que todos os dados na tabela de preparação estão corretos, uma única instrução colocará os dados em seus devidos lugares:

	INSERT INTO realtable SELECT * FROM stagingtable;
Este é um ótimo método porque os dados são inseridos rapidamente no banco de dados. Você pode utilizar-se da definição da tabela de preparação existente para construir suas consultas de teste. Você pode também decidir como manipular registros com dados ruins -- mesmo que seja para limpá-los ou removê-los.

Colaboradores: Wayne Armstrong wdarmst em bacchus.com.au, Nigel J. Andrews nandrews em investsystems.co.uk, Martijn van Oosterhout kleptog em svana.org, Jan Wieck JanWieck em Yahoo.com


Comentários e Correções são bem vindos. Sugestões e contribuições de itens também são bem vindos. Envie-os!.
Copyright A. Elein Mustain 2003
Traduzidos por Juliano da Silva Ignacio

Google
Search General Bits & varlena.com Search WWW