Desmistificando o SELECT no SQL Server: Introdução

Salve galera. Desde que os dinossauros morreram, eu não posto nada aqui! Bom, a causa é a vida , etc… Mas pretendo voltar a ativa.

Agora que realizei um pequeno sonho (passei no exame 070-432) pretendo escrever mais,  compartilhar mais, para aprender mais,e  é claro, tentar mais provas 🙂

Hoje vou iniciar uma série de posts que eu acredito que possa ajudar muitos desenvolvedores. Umas das maiores dificuldades que já vi, é entender como funciona o processamento das nossas queries, internamente no SQL Server. Isso é a chave para escrever consultas mais eficientes. É por isso que inicio a série:  “Desmistificando o SELECT no SQL Server”.

Pra me ajudar conto com o livro Inside SQL Server 2008: T-SQL Querying e o BOL. Se eu usar alguma outra fonte, vou citar. É claro que isso não é uma aula, e sim uma forma de exercitar e compartilhar o que estou aprendendo também. Portanto, estou sujeito a erros, e os comentários estão ai pra gente conversar!!!

Irei usar os exemplos do livro, adptando-os para uma realidade mais brasileira :).
O cenário é simples: Uma tabela de clientes e uma de pedidos (pra variar…).
Os scripts para a criação das tabelas e população que irei usar, estão aqui:

 

Irei usar SQL Server 2008. Mas boa parte disso tudo vale para o 2005 também. Irei citar os momentos em que houver alguma diferença grande.

Nestes posts irei falar sobre o processamento lógico da query. Pra algumas pessoas que já conhecem alguns detalhes, como o plano de execução, podem ficar confusas com a ordem do processamento. Mas desde já adianto que existe uma diferença entre o processamento físico e lógico. Vamos nos concentrar somente no processamento lógico da coisa.

Pra começo de conversa, a sintaxe básica de todo comando SELECT, no SQL Server, é assim:

Estamos acostumados a ver que a maiorias das linguagens, seja compilada ou interpretada, ler o código do início e compila/interpreta a partir desse início.

Com o SQL é diferente. Cada cláusula gera uma saída, que pode ser uma tabela virtual (que só é acessada internamente pelo sql), ou um cursor (não é o mesmo cursor que estamos acostumados a ver, é interno). Essa saída é usada pela próxima etapa, no caso de uma tabela virtual, ou é enviada ao cliente, no caso do cursor. A ordem dos comandos a ser executada será essa:

——————————————————————————————
1º – FROM
É aqui que os JOINs serão processados. Os filtros da cláusula ON também serão avaliados e por fim, essa etapa irá gerar uma tabela virtual.

2º – WHERE
Como todos já sabem, o WHERE responsável por aplicar os filtros na tabela virtual gerada pelo FROM. É gerada uma nova tabela virtual aqui.

3º – GROUP BY
O GROUP BY pega a tabela virtual gerada no WHERE e agrupa as linhas conforme soliticado.
Outra tabela virtual é gerada.

4º – HAVING
Aqui serão aplicados os filtros baseados em funções agregadas. Uma tabela virtual com as colunas que passaram nos filtros é gerada.

5º – SELECT
Finalmente, as expressões contidas no SELECT são avaliadas. Isso inclui os alias que damos as colunas. DISTINCT e TOP também são processados nesta etapa. Uma tabela virtual é gerada.

6º – ORDER BY
Por fim, o ORDER BY faz a ordenação dos registros para serem apresentados. A saída dele é um cursor que será retornado ao cliente que está executando a query.
——————————————————————————————

Um efeito interessante disso tudo é fácil de perceber:

Query 1:

 

Query 2:

Query 1 rodou!!!

Resultado da execução da Query 1

Query 2 não rodou- Erro: Invalid column name 'ID'

Resultado da execução da query 2

Por que a primeira query dá certo, e a segunda não ?
Simples: Lembra que eu disse que é na fase do SELECT que os alias são avaliados ?

ORDER BY é processado depois do SELECT. Assim quando o código chega no ORDER BY ele já tem a coluna com o nome “ID” associada com sua expressão.

Como o WHERE é processado antes do SELECT, ele não sabe o valor ou expressão que “ID” representa.

Bom, aqui eu me despeço mais uma vez. Nos próximos posts irei falar sobre cada etapa separadamente. O próximo será sobre o FROM. Irei mostrar o porque o LEFT JOIN é tão chato as vezes…

/** UPDATE 25/02/2012  

Antes de dar inicío ao post sobre FROM, resolvi dar um foco melhor a esse lance de “processamento lógico da query”.  

O próximo post fala sobre isso, e pode ser visto aqui.

**/

[]s
Rodrigo Ribeiro Gomes
MTA | MCTS