Archive for Agosto, 2008
“A ordem das cláusulas altera o resultado”
Sempre acreditei que a ordem das cláusulas numa consulta comum não interfere em nada no resultado. Porém, passei um dia investigando uma consulta que estava dando erro. A correção veio como de uma simples alteração na ordem das cláusulas. Difícil acreditar, né?
Esse erro aconteceu no Oracle, ao chegar em casa fui testar em outro e banco e pimba, aconteceu novamente. No SqlServer aconteceu o erro, já no mysql não consegui retratar.
Chega de embromação e vamos ao erro.
Vamos criar um simples tabela.
CREATE TABLE [tabela] (
[TIPO] [varchar](1),
[valor] [varchar] (3)
)
Na primeira coluna armazenaremos o tipo de dado que tem na seguda.
insert into tabela1 (tipo, valor) values (‘N’, ‘1′);
insert into tabela1 (tipo, valor) values (‘N’, ‘2′);
insert into tabela1 (tipo, valor) values (‘A’, ‘A’);
insert into tabela1 (tipo, valor) values (‘A’, ‘B’);
Agora uma simples consulta do tipo:
select * from tabela1
where 1=1
and convert(numeric, valor) > 0
and tipo = ‘N’
Gera o seguinte resultado:
Server: Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
Mas mudando a ordem para :
select * from tabela1
where 1=1
and tipo = ‘N’
and convert(numeric, valor) > 0
Obtemos:
TIPO valor
—- —–
N 1
N 2
(2 row(s) affected)
Ou no Oracle:
select * from tabela
where 1=1
and to_number(valor) > 0
and tipo = ‘N’
Detalhes: Isso aconteceu na versão do Oracle do trabalho e não na versão da minha casa.
Qual a possível explicação?
O mais perto que conseguimos acreditar, é no famoso curto circuito que estudamos em PD1. Ou seja, as cláusulas são avaliadas em algum sentido (no sqlserver de cima para baixo e no oracle de baixo para cima) e quando encontram alguma expressão que é falsa, ele já descarta o registro que está sendo avaliado. No nosso caso ele corre o risco de gerar um erro antes da primeira cláusula falsa, o que corre o risco de parar todo um processamento envolvido.
Soluções?
Fazer subconsultas para que não corra o risco de encontrar um erro, causa overhead mas não causa erro.
Outra coisa que aprendi sobre esse assunto, é que a ordem das tabelas no FROM da consulta também interfere em algumas consultas. Pelo menos no oracle ele olha as tabelas de trás para frente, então o ideal é colocar as tabelas com menos registros no final da lista, para que ele possa diminuir o trabalho de juntar tudo.
Estou a espera de melhores explicações e melhores soluções.
[]’s
1 comment Agosto 27, 2008
Hello Blog!
Agora tenho um blog. Grande merda. Pretendo colocar dicas e descobertas do mundo da programação (leia-se java) e outras coisas da computação.
[]’s
1 comment Agosto 27, 2008