[firebase-br] Índice de expressão e stored procedure
Daniel / Tecnobyte
temp2 em tecnobyte.com.br
Qua Abr 9 00:55:42 -03 2008
Tenho a seguinte tabela:
CREATE TABLE Pessoa(
...
Identidade VARCHAR(20) COLLATE PT_BR,
...);
Neste campo "Identidade" o usuário poderá um número de identidade com ou sem formatação, incluindo o órgão expedidor quando for o caso.
Exemplos:
001.002.003 SSP/RO
001002003 SSP/RO
001002003 SSP-RO
Mas neste caso desejo criar um índice permita pesquisar rapidamente sem informar a formatação e o sistema deverá encontrar em qualquer dos formatos acima. Além disso quero que estes exemplos acima sejam considerados iguais e não seja permitido duplicar.
Para começar fiz alguns testes com índice baseado em expressão e com função interna funcionou perfeito. Exemplo:
CREATE UNIQUE ASC INDEX Idx_Pessoa_Identidade2 ON Pessoa
COMPUTED BY(UPPER(Identidade));
SELECT * FROM Pessoa
WHERE UPPER(Identidade) = '1'
PLAN (PESSOA INDEX (IDX_PESSOA_IDENTIDADE2))
Então pensei: crio uma stored procedure que retornará apenas os dígitos e letras contidos no número do documento e indexo com base neste procedimento, como segue:
SET TERM ^ ;
CREATE OR ALTER PROCEDURE Proc_NumDoc(NumDoc VARCHAR(20))
RETURNS(Retorno VARCHAR(20)) AS
DECLARE VARIABLE Ch CHAR(1);
BEGIN
Retorno = '';
WHILE (NumDoc IS NOT NULL AND NumDoc <> '') DO
BEGIN
Ch = UPPER(SUBSTRING(NumDoc FROM 1 FOR 1));
IF ((Ch BETWEEN '0' AND '9') OR (Ch BETWEEN 'A' AND 'Z')) THEN
Retorno = Retorno || Ch;
NumDoc = SUBSTRING(NumDoc FROM 2 FOR 20);
END
IF (Retorno = '') THEN
Retorno = NULL;
SUSPEND;
END^
SET TERM ; ^
CREATE UNIQUE ASC INDEX Idx_Pessoa_Identidade ON Pessoa
COMPUTED BY((SELECT Retorno FROM Proc_NumDoc(Identidade)));
Isto resolveu o problema da duplicação, embora a mensagem tenha ficado esquisita. Veja:
---------------------------
attempt to store duplicate value (visible to active transactions) in unique index "@1"
---------------------------
O maior problema é que o índice deveria ter sido usado no SELECT abaixo, mas não foi. Veja:
SELECT * FROM Pessoa
WHERE ((SELECT Retorno FROM Proc_NumDoc(Identidade))) = '1'
PLAN (PROC_NUMDOC NATURAL)
PLAN (PESSOA NATURAL)
---
Sei que posso resolver o problema criando um campo extra onde eu deveria armazenar o número do documento sem a formatação e fazer toda a indexação e pesquisa sobre este campo. Este poderia ser alimentado via trigger, mas é uma gambiarra terrível. rsrs
Outra opção seria gravar tudo sem formatação, uma vez que não dá para forçar uma formatação padrão devido a natureza do dado (como trata-se de identidade, RG, para cada UF pode haver um formato diferente).
Enfim, qualquer das opções não ficará perfeita. O ideal seria mesmo indexar desprezando-se a formatação.
Alguém tem alguma sugestão melhor para resolver o problema?
NOTA! Ainda não testei índice baseado em expressão com chamada a uma UDF.
Atenciosamente.
Daniel P. Guimarães
Tecnobyte Informática
www.tecnobyte.com.br
Mais detalhes sobre a lista de discussão lista