Archive for Agosto 27th, 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


Calendar

Agosto 2008
S T Q Q S S D
    Set »
 123
45678910
11121314151617
18192021222324
25262728293031

Posts by Month

Posts by Category