Relâmpago: Como usar sp_helptext

Essa procedure permite você trazer informações das definições (codigo-fonte) de vários módulos, como triggers, procedures , views, funções, etc.

A sintaxe é:

EXEC sp_helptext ‘schema.NomeObjeto’

O objeto deve estar no mesmo banco onde se está executando o comando acima. Lembre-se que se a definição do objeto estiver criptografado, você não conseguirá ver. Por padrão, a procedure vai exibir no máximo 255 caracteres por linha. (Caso tenha uma linha com mais que isso, podem ocorrer problemas na execução pois ela vai quebrar a continuação da linha).

DICAS:

  • Você pode configurar query shortcuts (veja meu post sobre isso) para facilitar o uso. Em suma, você pode atribuir um atalho a chamada da procedure.
  • Se você optar por exibir no modo “Grid” a formatação do GRID acaba danificando a formatação original..Uma boa técnica é escolher exibir o resultado em texto. Atalho para isso é “CTRL + T”.

Rodrigo Ribeiro Gomes
[]’s

Advertisements

Novidade no Blog: Posts Relâmpagos

relampagoV

Apresento a vocês, o espaço “Relâmpago!”. O objetivo deste espaço é colocar post breves com informações e dicas em resposta aos termos pesquisados pelas pessoas. Por exemplo, se eu ver que você chegou ao blog através do termo “como usar o sp_helptext” eu irei tentar escrever um post breve sobre isso, e é claro fornecer informações úteis! A idéia é não ter um post longo, mas que tente sanar boa parte da sua dúvida e ainda te fornecer mais algumas detalhes e outros direcionamentos. É claro que estes termos podem gerar posts mais longos, então se for o caso poderei colocar na fila de posts. Também, nem de origem de pesquisas, mas até de conversas simples com colegas, situações do dia-a-dia, etc. Espero que gostem da idéia e que seja útil a nossa rede!

Para facilitar eles serão categorizados com o nome “relampago”, assim fica fácil procurar algo. Também irei sempre começar o nome com “Relâmpago: ”.

Impressões da Prova 70-457: SQL 2008–> 2012 (Part 1)

Bom hoje eu resolvi quebrar um pouco da série, e dar um feedback sobre a prova 70-457 (Transition your MCTS on SQL Server 2008 to MCSA: SQL Server 2012, Part 1). Como minha primeira prova de transição eu fiquei um pouco surpreso com o formato. A prova é tem 50 questões, dividas em duas partes de 25.

Na primeira parte, veio muita questão voltada a administração. Num primeiro momento, como eu não sabia, achava queria cair mais algo voltado para desenvolvimento. Questões bastantes conhecidas para quem fez as provas do 2005/2008 estavam lá. Uma que me lembro, e que é comum entre as atividades da maioria dos DBA’s, era sobre o logs do SQL Agent: Você precisava ver o output produzido pelas steps de um job a questão te perguntava como habilitar isso.  Backup & Restore tomou conta em umas 3 ou 4 questões. Uma delas te perguntava quais os passos para restaurar um backup do SQL Server 2005 para o 2012. Falando em passos, uma coisa na prova deixou ela mais fácil: as perguntas cujo a resposta era composta por várias ações sempre tinham o número de passos. Isso facilita um pouco quem não domina determinado assunto, mas tem alguma noção. Por exemplo, a pergunta final do backup acima era mais ou menos assim:

“Quais os três passos para se completar a tarefa”

Em relação a alta disponibilidade caiu boas perguntas sobre as tecnologias novas e as velhas conhecidas, como replicação. Nas duas partes, existiam um grupo de respostas que eram repetidos em vários perguntas diferentes. No meu caso foi para essa parte de HA, e na parte de Query (a segunda parte da prova). O que predominou nesse assunto foi comparar qual determinada tecnologia é melhor em dada situação. Acho que essa abordagem já é conhecida. Também, me lembro de 1 ou 2 perguntas sobre Failover Cluster, que mantém o mesmo padrão de provas anteriores (gerenciamento do cluster, atualização, fazer o failover, etc.).

Em um mix bem bacana, caiu perguntas sobre PBM, Audit, XE e profiler. A maioria delas te dava uma situação e perguntava qual tecnologia usar. Me recordo de algumas sobre Audit, perguntando sobre a sintaxe para fazer determinada tarefa. Perfmon também deu alguns sinais de vida nesse tipo de questão comparativa.

A outra parte, veio querying pesado. Como eu sou fã da parte de perfomance já adianto que caiu umas bem “desafiadoras”, porém algumas mal formuladas. Em uma dessas, o questão te dava uma querie que usava uma UDF e perguntava qual das opções era a melhor escolha para otimizar a consulta.  Funções analíticas não me recordo de muita coisa, apenas de uma questão, onde você deveria saber a diferença entre LAG E LEAD e o efeito da cláusula OVER sobre ela. (aproveito para compartilhar este artigo do Fabiano Amorim, no simple talk, que te dá uma visao bacana dessa funções e uma boa explicação sobre o conceito do  “frame/window”). Pode crer, este artigo me salvou! Smile

No geral a parte de query caiu perguntas bem conhecidas dos outros exames de query, incorporando algumas com as novas funcionalidades. Dessa vez eu não vi nenhum para fazer a análise de um plano de execução. Mas teve view indexada, data modification, etc.

SSIS teve sua presença em umas 4 ou 5 questões, junto SQL Server Agent, jobs, etc.

Em suma, eu gostei da prova, achei cheia de questões legais e senti uma dificuldade maior do que nas outras provas. Talvez seja porque ainda não estivesse muito em contato com a nova versão do produto ( e já tá vindo a 2014 pra piorar melhorar a minha vida, rs!). Uma dica que eu dou é ver o “What’s New” do 2012, ver o que tem de novo, e estudar esses assuntos (no próprio link tem breve explicações que já ajudam). Tem muita coisa bacana que veio para resolver problemas antigos, assim quem já tem alguma experiência desde a versão 2005, consegue assimilar tranquilo as novas funcionalidades.

No mais é isso galera, até o próximo post. A nossa série sobre o SELECT ainda não parou, em breve a continuação. Quando fizer o Part 2, eu posto aqui os resultados.

Também aproveito para falar que post da parte de administração também estarão em breve saindo do forno. E se você tem alguma sugestão, não deixe de usar o espaço “on demand” para colocar algum assunto. Até a próxima!


[]’s
Rodrigo Ribeiro Gomes

DESMISTIFICANDO O SELECT no SQL SERVER: O FROM – Parte 1

 

E após mais um longo tempo sem postar nada,  vou dando continuidade a nossa série do processamento lógico de um SELECT.

Hoje vamos falar sobre o FROM. No último post eu tentei uma breve explicação sobre o que é o processamento lógico, e a comparação dele com o processamento físico. O objetivo desta série é saber como o SQL Server “entende” uma query e como ele vai manipular as informações para produzir o resultado codificado pelo seu comando de SELECT. De posse desta informação, você pode começar a manipular suas queries e entender porque determinada consulta não está trazendo um resultado que você espera, ou rapidamente poder montar uma solução para um determinado problema.

Assim, vamos falar do processamento lógico como se fosse realmente o que SQL Server faz, e por mais que seja absurdo, não pense em performance agora. Concentre-se em entender qual a semântica por trás de um simples SELECT.

Para recapitular, um simples SELECT: (Utilize os scripts deste post para criar as tabelas)

SELECT
    C.clienteID
    ,C.cidade
FROM
    dbo.Cliente C

Se eu estivesse aprendendo banco de dados agora, e te perguntasse o que esse código faz, provavelmente você diria: “Retorna o ID e cidade de todos os registros da tabela ‘Cliente’ ”. E está certo! Você sabe o que vai ser retornado. Agora se eu te perguntasse, como o SQL Server está fazendo para acessar estes dados você poderia me responder: “Ele está lendo a tabela inteira diretamente”, ou “Ele está usando o índice da tabela”. Não importa como o SQL Server está fazendo, mas você sabe que o que ele está tentando fazer é ler a tabela inteira, e retornar 2 colunas. Independente de como ele vai fazer isso, porque é isto que a query está pedindo.

Agora, imagine que você quisesse saber o seguinte:

Trazer todas as cidades da tabela cliente, junto com o total de pedidos feitos por clientes cujo ID é < 3.

Em uma primeira tentativa, a query abaixo poderia ser uma solução:

SELECT
    C.cidade
    ,COUNT(P.PedidoID) as TotalPedidos
FROM
    dbo.Cliente C
    LEFT JOIN
    dbo.Pedido P
        ON P.ClienteID = C.ClienteID
WHERE
    P.ClienteID < 3
GROUP BY
    C.cidade
cidade               TotalPedidos
-------------------- ------------
Brasilia             5

 

Percebam que a cidade “Goiânia” não aparece no resultado, e a nossa regra de negócio exige que ela apareça. Mas porque ? Onde está o problema ? A coisa fica mais interessante quando você apenas muda um filtro de lugar …

SELECT
    C.cidade
    ,COUNT(P.PedidoID) as TotalPedidos
FROM
    dbo.Cliente C
    LEFT JOIN
    dbo.Pedido P
        ON P.ClienteID = C.ClienteID    
        AND P.ClienteID < 3
GROUP BY
    C.cidade
cidade               TotalPedidos
-------------------- ------------
Brasilia             5
Goiania              0

Agora sim o resultado retornado foi o que queríamos. Porque apenas ao mudarmos o filtro de lugar o resultado produzido foi diferente ? Repostas a estas perguntas serão respondidas quando você entender o processamento lógico.

Neste ponto, você não deve se preocupar em COMO o SQL Server irá fazer determinar operação, mas sim O QUE ele entenderá que deve ser feito. Isso é o processamento lógico!!!!

Conforme vistos no primeiro post, vamos falar agora fase por fase, explicando suas entradas e saídas. Hoje o nosso foco é a primeira fase, a parte do FROM.

 

Tabelas Virtuais

No processamento lógico cada fase produz um resultado, e esse resultado é passado para a próxima fase. Para facilitar, imagine que cada fase produz uma tabela virtual. Eu não vou chamar de “temporária” para você não confundir com as tabelas temporárias que existem na linguagem. Essas “tabelas virtuais” são passadas de fase por fase, e a próxima fase só enxerga a tabela que foi passada a ela, inclusive somente as suas colunas (tem algumas exceções, mas esqueça por agora). Por questões de nomenclatura, eu vou atribuir nomes a essas tabelas para ir facilitando nossa compreensão, mas lembre-se que essas tabelas só são “enxergadas” pelo SQL Server.

A cláusula FROM

A cláusula FROM é a primeira a ser processada. Lá é onde ficam as nossas tabelas e as operações que fazemos com elas.Você pode fazer JOINS, APPLYs e PIVOTs com as tabelas. A fase de processamento do FROM é divido em sub-fases. Cada sub-fase também produz uma tabela virtual que é passada para a próxima sub-fase e por ai em diante. No final, a tabela virtual resultante é retornada do FROM e passada para a próxima fase,que é o WHERE (que veremos em outro post).

A sintaxe do FROM é a seguinte:

FROM
   input OPERAÇÃO input OPERAÇÃO input OPERAÇÃO input [etc…]

Percebam que eu usei o nome “input”. Vou chamar assim porquê esse input pode ser qualquer coisa que retorne uma estrutura de tabela:

  • Uma tabela
  • Uma view
  • Uma tabela derivada
  • Uma CTE
  • Uma Table-Valued Function

NOTA: Se você não conhece essas coisas ainda, não se preocupe. Se concentre que um input é algo que representa uma estrutura de tabela.

A OPERACAO é o que será feito entre os dois inputs. Ela pode ser:

  • JOINS (CROSS,INNER, LEFT, RIGHT,FULL)
  • APPLY (CROSS, OUTER)
  • PIVOT (PIVOT, UNPIVOT)

        As sub-fases da cláusula FROM variam de acordo com cada uma dessas oparações. A sub-fases para um “INNER JOIN” são diferentes para um CROSS JOIN que são diferentes para um “CROSS APPLY” ou um “UNPIVOT”.
    Para simplificar, vamos inicialmente falar somente sobre as sub-fases para todos os tipos de JOINS, pois estes são mais fáceis de se compreender e são usados mais frequentemente.
    Em outro post entraremos em mais detalhes sobre as sub-fases dos outros operadores.

Operadores de Tabela

As operações realizada com as tabelas são feitas através de operadores de tabela. Por exemplo, um “INNER JOIN”. Os operadores de tabela seguem algumas regras já conhecida por nós lá na matemática…Por exemplo, você tem a operação de SOMA. O que é preciso para fazer uma soma acontecer? Você precisa de 2 números para fazer a SOMA. Neste caso, os 2 números chamamos de “operando” e a “soma” é o operador, o qual é representado pelo sinal “+”.

Aqui é a mesma coisa. Por exemplo, para fazer um CROSS JOIN, você precisa de dois inputs. O operador é representado pelo seu próprio nome. Os dois inputs são os nossos operandos. Em versões futuras do SQL Server, podem ser lançados operadores que requeiram somente um input, ou três, ou nenhum …

Ainda, na matemática, se você tem a expressão “1 + 1 + 2”, Você pode fazer “1 + 1”, e do resultado, somar com 2. Ou seja o operador só trabalha com 2 operandos por vez.
Igualmente com os operadores de tabela, se existir mais de 1 operando, é feito a operação entre os 2 primeiros operandos, e o resultado é usado como input para o próximo operador, juntamente com o o outro input, e por ai vai até acabar:

input_A OPERADOR input_B OPERADOR input_C OPERADOR input_D:

    input_A OPERADOR input_B  = input_AB

    input_AB OPERADOR input_C = input_ABC

    input_ABC OPERADOR input_D = input_ABCD

Como acabou as operações, o resultado seria o “input_ABCD”.

As tabelas virtuais retornadas por cada sub-fase serão passadas para a próxima fase, ou serão usadas como inputs para próximas operações, se houver, até acabar todas as cláusulas no FROM. No final, a tabela virtual resultante é passada para a fase de processamento do WHERE. Lembre-se que podemos misturar operadores de diferentes operações: 

A JOIN B APPLY C PIVOT D.

Simplesmente, o resultado do JOIN de A com B é usado para fazer o APPLY com C, e este último resultado é usado para fazer o PIVOT com D.

Mas, de novo, ressalto que iremos apenas falar de JOINs.

AS SUB-FASES

1ª SUB-FASE: Produto Cartesiano

Nesta fase, é feito um produto Cartesiano entre os inputs. Para quem não lembra o produto cartesiano vem lá da teoria de conjuntos. Ele é uma operação onde todos os elementos de um conjunto são combinados com todos os elementos de um outro conjunto. Isto gera um conjunto com TODAS AS COMBINAÇÕES POSSÍVEIS.

Trazendo para o nosso mundo, nesta sub-fase, será gerado uma tabela virtual contendo todas as combinações possíveis de linhas entre os dois inputs.
Se o input da esquerda contém 5 linhas, e o input da direita contém 2 linhas, a tabela virtual gerada aqui vai conter 5 x 2 = 10 linhas. Cada linha da esquerda será associada com cada linha da direita.

E é exatamente isso o que um CROSS JOIN faz. Ele serve para combinar TODAS AS LINHAS dos dois inputs. Quando a operação que está sendo executada é um CROSS JOIN, esta é a única sub-fase que executada para o operador que está sendo processado.

Aqui será retornado a tabela virtual “TVF1”.

JOINS RECAP:

Joins são operações que usamos para combinar linhas de dois inputs. O resultado de uma operação de JOIN é uma tabela que contém as colunas dos dois inputs. Dependendo do JOIN, você pode especificar uma condição, isto é, uma lógica, para determinar as combinações de linhas que vão ser geradas. Podemos combinar linhas usando APPLY. Existe também operadores que podemos combinar dois inputs. Eles diferem um pouco dos JOINS porque combinam colunas, isto é, juntam colunas de diferentes inputs. São: UNION, INTERSECT E EXCEPT. Mas isso é assunto pra outro post, outra série!

 

Bom, por hoje é só. No próximo post irei falar sobre as outras fases.  Até lá, vá revendo os tipos de JOINS. Para este momento entender e vê exemplos de JOINs irão facilitar ainda mais sua compreensão.

E como sempre, desculpem os erros de português. A cada post estou tentando melhorar e ser mais claro. Qualquer dúvida, sugestão, crítica, ou elogios, utilize os comentários! Seu feedback sempre é bem vindo!

[]’s
Rodrigo Ribeiro Gomes
MCTS | MCITP

Desmistificando o SELECT no SQL Server: Processamento Lógico vs Processamento Físico

Quando eu começei a ler sobre o processamento lógico das queries, eu “boiei” muito.
Sabia que era um assunto bem legal, mas nao entendia realmente o que era.

Depois de algum tempo de leitura e pesquisa, acho que finalmente entendi, e, por experiencia própria acredito que seja mais do que importante entender bem esse assunto.

Para o SQL Server processar aquele comando SQL, ele tem algo como “regras”.
Ele vai validar o comando pra ver se está de acordo com a sintaxe do SQL, checar se as tabelas existem, etc…

Todo esse procedimento segue uma lógica. Essa lógica guia o modo como a engine do SQL Server irá interpretar o comando.
Por exemplo, veja a seguinte query: (Os scrips para criação dessas tabelas está aqui)

SELECT
     C.cidade
    ,COUNT(P.pedidoID)
FROM
    dbo.Cliente C
    LEFT JOIN
    dbo.Pedido P
	   ON P.clienteID = C.clienteID
GROUP BY
    C.cidade

É uma query muito simples. O que ela faz é trazer a quantidade de pedidos por cidade.
Vamos viajar um pouco. Imagine que você fosse o SQL Server e estivesse responsável por processar a query.
De cara, você começa a processar a query a partir do início, isto é, da cláusula SELECT:

Ai você dá de cara com esse primeiro trecho do comando:

SELECT
	c.cidade

Ai você se pergunta, “C.cidade” ? Qual tabela o alias “C” representa ?
Opa, você percebeu que nao podemos começar o processamento pelo SELECT, porque primeiro precisamos saber quais as tabelas e alias o desenvolvedor informou na query.

E onde estão essas informações ? Na cláusula FROM!!

Agora veja esta outra query:

SELECT DISTINCT
     UPPER(C.cidade) AS NomeCidade
FROM
    dbo.Cliente C
ORDER BY
    NomeCidade

Essa query pode ter várias interpretações diferentes, isto é, várias “lógicas de processamento” diferentes.Cada lógica escolhida no seu processamento vai produzir um resultado diferente. Quer ver ? Então vamos lá.

Vamos supor que a lógica de processamento que voce escolheria fosse a seguinte: (de novo, imaginando que você  é o SQL Server)

1º – FROM
2º – ORDER BY
3º – SELECT
Bem vamos lá, o FROM seria moleza. Você teria apenas que ler os dados da tabela Cliente e atribuir o alias “C” a ela.

Logo em seguida viria o ORDER BY. Opa, temos um problema, a tabela Cliente nao tem uma coluna ‘NomeCidade‘. Essa coluna é um alias definido no SELECT, e como você ainda não processou o SELECT, não sabe da existencia desse alias. Nesse caso, representando o SQL Server, o que fazer? Simples: Informaria um erro ao usuário:

“Erro 0000: A coluna NomeCidade nao foi encontrada”

Assim, nessa ordem de processamento o resultado seria um erro. Agora, vamos imaginar que a ordem escolhida fosse essa:

1º – FROM
2º – SELECT
3º – ORDER BY

De novo, a primeira fase é processar o FROM: apenas ler tabela Clientes e atribuir o alias “C” a ela.
Agora, vem a fase do SELECT. Nessa parte ele menciona “C.cidade”. Como já processamos o FROM, sabemos que o “C” representa a tabela “Cliente”. Legal, com isso nós vimos que o desenvolvedor está querendo referenciar uma coluna chamada “cidade” da tabela Cliente. O próximo passo seria verificar se a coluna realmente foi retornada pelo FROM, mas não se preocupe com isso agora.

Continuando o processamento do SELECT, aplicariamos a funcao UPPER na coluna “C.cidade”. Por último, nós iríamos associar o alias “NomeCidade” ao resultado desta função. Até aqui tudo bem.

Enfim, processaríamos o ORDER BY. Como já processamos o SELECT, nó sabemos que o nome “NomeCidade” é uma alias pro resultado da expressão “UPPER(C.Cidade)”

Agora é so ordenar os dados de acordo com o resultado dessa função, e pronto!

Tá vendo ? Olhe só que interessante.
Na primeira tentativa, o nosso processamento resultou em um erro.
Na segunda, apenas por trocar o ORDER BY de lugar com o SELECT, ja produziu um resultado sem erros.

Isso não se resume a resultados com erros ou não. Dependendo de como você acha que sua query ai ser executada, você pode imaginar que vai vir uma coisa, quando na verdade vem outra…

É por isso que é bastante importante entender como o SQL Server irá avaliar seu comando SQL. Entender como é a lógica usada por ele, o que chamamos de processamento lógico da query (Logical Query Processing). Entendo o processamento lógico da query é a chave para escrever consultas mais eficientes e robustas.

E o processamento físico ?

O processamento lógico na verdade é só um conceito… A microsoft apenas implementou as regras deste conceito. O modo como o SQL Server vai acessar os dados, filtrar, etc… “são outros 500 …”.

Você so precisa saber que o resultado produzido pelo processamento físico deve ser exatamente o mesmo produzido no processamento lógico. Assim, quando formos analisarmos o plano de execução (que indica como o SQL irá executar a query) iremos ver passos em uma ordem muito diferente do processamento lógico, mas pode ter certeza que o resultado produzido, será o mesmo do processamento lógico.

Bom, espero que esse post nao tenha ficado confuso. Esse lance de processamento físico e lógico vai ser esclarecido conforme formos vendo cada fase do processamento lógico.

Qualquer dúvida, sugestão, crítica, etc., por favor, coloque nos comentários que estarei respondendo.
Até a próxima.

[]’s
Rodrigo Ribeiro Gomes
MTA|MCTS

Desmistificando o SELECT no SQL Server – Parte 1

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:

CREATE TABLE
	dbo.Cliente
	(
		 clienteID INT NOT NULL CONSTRAINT pkCliente PRIMARY KEY
		,cidade	VARCHAR(20) NOT NULL
	)
GO

INSERT INTO Cliente(clienteID,cidade) VALUES(1,'Brasilia');
INSERT INTO Cliente(clienteID,cidade) VALUES(2,'Brasilia');
INSERT INTO Cliente(clienteID,cidade) VALUES(3,'Brasilia');
INSERT INTO Cliente(clienteID,cidade) VALUES(4,'Goiania');
GO

CREATE TABLE
	dbo.Pedido
	(
		 pedidoID	INT NOT NULL CONSTRAINT pkPedido PRIMARY KEY
		,clienteID	INT NULL CONSTRAINT fkClienteID_pedido_cliente REFERENCES Cliente(ClienteID)
	)
GO

INSERT INTO Pedido(pedidoID,clienteID) VALUES(1,1);
INSERT INTO Pedido(pedidoID,clienteID) VALUES(2,1);
INSERT INTO Pedido(pedidoID,clienteID) VALUES(3,2);
INSERT INTO Pedido(pedidoID,clienteID) VALUES(4,2);
INSERT INTO Pedido(pedidoID,clienteID) VALUES(5,2);
INSERT INTO Pedido(pedidoID,clienteID) VALUES(6,3);
INSERT INTO Pedido(pedidoID,clienteID) VALUES(7,NULL);
GO

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:

SELECT DISTINCT TOP (<expressao_top>)
	<lista_select>
FROM
	<tabela_esquerda>  <tipo_de_join> JOIN <tabela_direita> ON <predicado_ON>
WHERE
	<predicado_WHERE>
GROUP BY
	<lista_group_by>
HAVING
	<predicado_HAVING>
ORDER BY
	<lista_ORDER_BY>

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:

		SELECT
			c.ClienteID as ID
		FROM
			dbo.cliente c
		ORDER BY
			ID

Query 2:

		SELECT
			c.ClienteID as ID
		FROM
			dbo.cliente c
		WHERE
			ID > 1

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

E se Chuck Norris fosse DBA ?

Para distrair um pouco: recentemente eu encontrei um post muito engraçado ( para os que entendem ) sobre o famoso Chuck Norris versão DBA.

Abaixo uma prévia do que pode ser encontrado nesse blog:

[…]

  • Chuck Norris não faz DELETEs. Ele olha para os registros e eles correm de medo.
  • MSSQL Server É muito mais rápido que Oracle. Basta que o DBA seja CHUCK NORRIS.
  • SELECT SUM(FORÇA) FROM CHUCK_NORRIS;
    Internal error. Don’t call the support.
  • SELECT CHUCK_NORRIS;
    Drop database sucessful.
  • Chuck Norris instala o MSSQL Server em um Pentium 100MHZ. Rodando Solaris. A partis dos fontes.
  • Se disser ao DBA Chuck Norris que “o problema está no banco”, é melhor que esteja se referindo ao Itaú.
  • TRIGGERS tem este nome porque Chuck Norris sempre ameaçava atirar no banco quando ele não fazia algo automático.

[…]

[]s
Rodrigo Ribeiro Gomes