0% acharam este documento útil (0 voto)
524 visualizações80 páginas

Apostila Transact SQL Oficial

1. O documento apresenta uma introdução sobre SQL e seus principais comandos DML para manipulação de dados em bancos de dados relacionais. 2. São criados um banco de dados de exemplo e uma tabela para armazenar dados de clientes, com três colunas de tipos de dados diferentes. 3. Dois registros são inseridos na tabela usando o comando INSERT para demonstrar a manipulação de dados.

Enviado por

Ademir Oliveira
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
524 visualizações80 páginas

Apostila Transact SQL Oficial

1. O documento apresenta uma introdução sobre SQL e seus principais comandos DML para manipulação de dados em bancos de dados relacionais. 2. São criados um banco de dados de exemplo e uma tabela para armazenar dados de clientes, com três colunas de tipos de dados diferentes. 3. Dois registros são inseridos na tabela usando o comando INSERT para demonstrar a manipulação de dados.

Enviado por

Ademir Oliveira
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 80

1

TRANSACT - SQL









































2







Indice

1. O que Datatype
2. DML SELECT, INSERT, UPDATE e DELETE
3. Utilizao do comando SELECT
4. Exibindo os dados de todas as colunas da tabela Funcionario
5. Utilizao do comando INSERT
6. Utilizao do comando UPDATE
7. Utilizao do comando DELETE
8. A clusula WHERE Critrio Resumo
9. IN / NOT IN
10. BETWEEN /NOT BETWEEN
11. LIKE / NOT LIKE / SCAPE
12. IS NULL / IS NOT NULL
13. A clusula ORDER BY
14. Ordenando pela posio da coluna
15. Argumentos
16. Group By
17. Funes de Totalizao
18. Utilizando Group By HAVING
19. CASE
20. Case com SELECT
21. Case com ORDER BY
22. Case com UPDATE
23. Case com HAVING
24. A clusula UNION
25. UNION
26. UNION ALL
27. Joins Transformando dados em informao
28. INNER JOIN
29. LEFT JOIN
30. RIGHT JOIN
31. FULL JOIN
32. CROSS JOIN
33. Join com mais de duas tabelas
34. Evitando Ambiguidade
35. UPDATE COM JOIN


3

36. DELETE COM JOIN
37. Joins entre tabelas que possuem Chaves Compostas
38. SUBQUERY
39. Subquery Introduzida com Operador de Comparao
40. Subquery Introduzida com IN ou NOT IN
41. Subquery Introduzida com EXISTS e NOT EXISTS
42. Substituindo Subqueries
43. Subqueries Aninhadas
44. UPDATE COM SUBQUERY
45. DELETE COM SUBQUERY


























4

INTRODUO



A utilizao de databases para o armazenamento de dados, surge nos anos 60, e o primeiro
modelo a ser utilizado foi o Hierrquico, seguidos pelos modelos Rede, Relacionais, Dedutivo e o
Objeto.
A linguagem SQL surge com a criao do Modelo Relacional proposta pelo Dr. Edgard
Frank Codd j nos anos 70.



O QUE SIGNIFICA A SIGLA SQL



SQL o nome que foi atribudo linguagem declarativa utilizada no tratamento de dados
armazenados no formato relacional.
A sigla SQL quer dizer Structured Query Language, ou seja, Linguagem Estruturada de
Pesquisa e, foi idealizada e desenvolvida nos laboratrios da IBM USA.
Quando criada recebeu outro nome, SEQUEL, que significava Structured English Query
Language Linguagem Estruturada em Ingls para Pesquisa.
A linguagem SEQUEL foi utilizada para demonstrar a viabilidade do modelo de
armazenamento relacional idealizado pelo Dr. Cood.
Com o passar do tempo a linguagem teve seu nome alterado para SQL, mas l nos Estados
Unidos seu nome ainda pronunciado como Sequel.
Tambm com o passar do tempo, com sua aceitao e utilizao pelos profissionais de banco
de dados, a linguagem SQL acabou se tornando um padro. Na realidade, surgiram vrios dialetos
desta linguagem e houve a necessidade de padronizar a sua utilizao.
Sendo assim, em 1986 ela foi padronizada pelo instituto ANSI e em 1987 pelo ISO.
A padronizao da SQL foi revista em 1992 e, justamente por isso passa a ser chamada de
SQL-92 ou SQL2.
Em 1999 houve outra reviso onde a linguagem passa a se chamar SQL:1999 ou SQL3.
SQL o nome que foi atribudo linguagem declarativa utilizada no tratamento de dados
armazenados no formato relacional.
Na padronizao, os comandos da linguagem SQL foram agrupados de acordo com suas
funes como segue:









5







1 DCL Data Control Language

GRANT

REVOKE




2 DDL Data Definition Language

CREATE

ALTER

DROP




3 DML Data Manipulation Language

SELECT

INSERT

UPDATE

DELETE





Apesar da padronizao, ainda h uma certa diferena na sintaxe da SQL utilizada pelas
empresas que desenvolvem os gerenciadores de banco de dados, e aqui neste tutorial, utilizamos a
sintaxe da Microsoft e vamos comear pelas demonstraes dos comandos da DM




DML DATA MANIPULATION LUANGUAGE





6


Na traduo, DML significa Linguagem de Manipulao da Dados, como foi dito anteriormente,
e ela abrange os comandos SELECT, INSERT, UPDATE E DELETE, ou seja, comandos para leitura,
incluso, alterao e excluso de dados.




DATABASE, TABELAS E DATATYPES




O QUE UM DATABASE



No SQL Server, um database o nome que se d para um conjunto de arquivos de dados e de
transaes.
Todo database do SQL Server tem pelo menos dois arquivos, uma para armazenar dados de
tabelas e de ndices e o outro para armazenar as transaes (comandos que inserem,
alteram e excluem os dados de uma tabela).
Esses databases podero, se necessrio, ter mais de um arquivo de dados e/ou mais de um
arquivo de transaes.
Como o objetivo deste tutorial exibir a forma de utilizao dos comandos DML, vamos aqui
criar um database com todas as opes definidas como default e com os arquivos de dados e de
transaes que o prprio SQL Server define durante a execuo do comando CREATE DATABASE.

Para tanto siga as instrues baixo:


Clique no menu Start / Programs / Microsoft SQL Server 2008/ SQL Server
Management Studio.
Conecte-se no SQL Server, apenas clicando no boto Connect.
Em seguida, na barra de menu, escolha a opo New Query.
Surge para voc uma rea onde os comandos so digitados e executados.
Escreva o comando abaixo para criar um database chamado db_Treinamento, com
todas as opes de armazenamento e dimensionamento definidas como default:

CREATE DATABASE [db_Treinamento]

Pressione a tecla F5 para executar o comando.
Em seguida, escreva o comando abaixo para acessar o database db_Treinamento,


7


selecione apenas esta linha e tecle F5 para execut-lo.


USE [db_Treinamento]


Observe no alto e do lado esquerdo da sua tela, que aparece o nome db_Treinamento
como o database corrente.



O QUE UMA TABELA



Uma Tabela um objeto bidimensional, composta por Colunas e Linhas, onde os dados so
armazenados dentro de um database.
O exemplo abaixo exibe uma Tabela chamada Cliente, formada pelas Colunas Cod_Cli
que representa um cdigo definido para o cliente, Nome_Cli que representa o nome do cliente
e Renda_Cli, que representa um valor para a renda dos clientes.
Nesta Tabela ainda h 2 Linhas de dados inseridas. Temos o cliente cujo cdigo o nmero 1
e o nome Agnaldo e o cliente de nmero 2 cujo nome Renata:











O QUE DATATYPE


Data type, ou tipo de dado, o formado no qual os dados de cada coluna de uma tabela so
armazenados em disco.
O Microsoft SQL Server oferece vrios datatypes que chamamos de built-in, ou seja,
construdos internamente. Eles so divididos em categorias como, por exemplo, categoria dos
datatypes numricos, caracteres, data, hora, etc.
Vamos utilizar alguns destes tipos de dados e, para atabela Cliente exibida acima, vamos
atribuir para a coluna Cod_Cli o datatype int, que s aceitar que se insira nela, nmeros inteiros.
Para a coluna Nome_Cli vamos devinir o tipo de dado varchar(100), que s aceitar dados no
formato caractere e que tenham at 100 dgitos.
E para a coluna Renda_Cli vamos utilizar o datatype decimal(10,2), que aceitar dados
Cod_Cli Nome_Cli Renda_Cli
1 Agnaldo 30000.00
2 Renata 5000.00


8

numricos com duas casas decimais.
Para que voc possa criar esta tabela, inserir suas duas linhas de dados e exibir seu
contedo, siga as instrues abaixo.
Na mesma tela e logo aps voc ter executado o comando USE [db_Treinamento] para
acessar este database, escreva os seguintes comandos:


-- Criando a tabela Cliente


CREATE TABLE Cliente
(
Cod_Cli int,
Nome_Cli varchar(100),
Renda_Cli decimal(10,2),
)


Na sequncia, selecione apenas comando acima e tecle F5 para execut-lo.
Para inserir os dados dos dois clientes em questo vamos utilizar o comando INSERT
(que ser visto em mais detalhes em outros tpicos deste tutorial). Ento, escreva
os comandos:


-- Inserindo dois Registros, ou seja, duas Linhas de dados na tabela Cliente


INSERT Cliente VALUES(1,Agnaldo,1000.00)
INSERT Cliente VALUES(2,Renata,500.00)


Neste primeiro momento, selecione cada um dos comandos acima e tecle F5 para execut-
lo.


Obs:

a - Quando voc for inserir dados no formado caractere, voc deve escrev-los entre
apostrofo, como Agnaldo e Renata.

b - Voc poderia ter selecionado os dois INSERTs de uma s vez para inserir os dois
clientes ao mesmo tempo, mas como voc est comeando a trabalhar com a sintaxe da SQL
interessante que voc execute os comandos um a um, assim se, por acaso, voc cometer
algum erro der sintaxe fica mais fcil detect-lo e corrigi-lo.



9

c - Voc pode escrever qualquer comando da sintaxe SQL em letras maisculas ou minsculas.

d - Por causa do Collation padro da instalao do software, o SQL Server no far diferena
no momento da pesquisa dos dados se, por acaso, voc digitar Agnaldo, AGNALDO,
aGNALDO, etc. Enfim, o SQL Server vai gravar na Tabela os dados do jeito que voc os
digitar, mas por causa do Collation padro da instalao da Instncia, da criao do database
e da definio da coluna que utilizamos em Nome_Cli, para encontrar os dados ele no far
diferenciao entre letras maisculas e minsculas.

e Collation o nome que se d ao conjunto de definiao de idioma, ordenao, acentuao,
etc, para o armazenamento e perquisa de dados em colunas caracteres.

f Os comentrios colocados nas demonstraes sempre aparecero na cor verde e, podem
ser escritos em apenas uma linha, utilizando para isso dois simbolos de subtrao (--),
Ou podero ser comantrios de vrias linhas e, para tanto devero ser escritos assim:

/*
Comentarios feitos m mltiplas Linhas so chamados de Comentrios em Bloco.
*/


Nosso prximo passo ser a exibio dos dados que acabaram de ser inseridos.
Para tanto, na mesma tela, escreva o comando abaixo:

SELECT * FROM Cliente


Selecione apenas a linha acima e pressione F5 para execut-la. Note que os dados
so exibidos na parte inferior da sua tela.

Pronto! Agora voc j tem um database, uma tabela com trs colunas, e duas linhas de dados
inseridas!
Se voc chegou at aqui, parabns pelos primeiros passos na sintaxe SQL da Microsoft.






DML SELECT, INSERT, UPDATE E DELETE



Como foi visto anteriormente, DML um grupo de comandos da linguagem SQL que significa


10

Data Manipulation Language Linguagem de Manipulao de Dados. Dela fazem parte os
comandos SELECT, INSERT, UPDATE e DELETE.



UTILIZAO DO COMANDO SELECT



Como voc j deve ter percebido, SELECT o comando da linguagem SQL que utilizamos
para selecionar/exibir os dados de uma tabela.
A sintaxe da SQL nos permite exibir dados de vrias maneiras atravs das variaes do
comando SELECT.
Para que voc possa conhecer estas possibilidades de sintaxe vamos criar, no database
db_Treinamento, uma outra tabela chamada Funcionario, vamos inserir nela cinco linhas de
dados e assim trabalhar com este objeto.


-----------------------------------------------------------------------

-- Acessando o database 50minutos

Use db_Treinamento

-----------------------------------------------------------------------



-- Criando a tabela Funcionrio

CREATE TABLE Funcionario
(
Cod_Func int,
Nome_Func varchar(100),
Sexo_Func char(1),
Sal_Func Decimal(10,2),
Data_Func Datetime
)

--- Inserindo dados na tabela Funcionario

INSERT Funcionario VALUES(1,'Marcos','M',1575.87,Getdate())
INSERT Funcionario VALUES(2,'Paulo','M',2500.50,Getdate())
INSERT Funcionario VALUES(3,'Roberta','F',1000.80,Getdate())
INSERT Funcionario VALUES(4,'Cristina','F',578.25,Getdate())


11

INSERT Funcionario VALUES(5,'Jos','M',600.00,Getdate())

----------------------------------------------------------------------

EXIBINDO OS DADOS DE TODAS AS COLUNAS DA TABELA FUNCIONARIO


Para exibir os dados de todas as colunas de uma determinada tabela voc pode utilizar uma
das duas sintaxes exibidas abaixo.

1 Exibindo os dados de todas as colunas de uma tabela utilizando asterisco para represent-
las:


--Exibindo os dados de todas as colunas de uma tabela


SELECT * FROM Funcionario

2 Exibindo os dados de todas as colunas de uma tabela especificando o nome de uma por
uma:

--Exibindo os dados de todas as colunas de uma tabela

SELECT Cod_Func,
Nome_Func,
Sexo_Func,
Sal_Func,
Data_Func
FROM Funcionario


3 - Exibindo os dados de todas as colunas de uma tabela na ordem desejada



Voc j deve ter percebido que para exibir os dados de todas as colunas da tabela em outra
ordem que no seja a da definio de sua estrutura, basta escrever o nome das colunas na
sequncia em que desejar exibi-las.




-- Exibindo os dados de todas as colunas de uma tabela na sequncia -- -- desejada


SELECT Sexo_Func,


12

Data_Func,
Cod_Func,
Nome_Func,
Sal_Func
FROM Funcionario




4 Exibindo os dados de algunas colunas de uma tabela



Agora ficou fcil, para exibir os dados de algumas colunas de uma tabela, basta escrever
apenas seus nomes no comando SELECT e execut-lo.


Exemplo_01

-- Exibindo os dados de algumas colunas de uma tabela

-- na sequncia desejada
SELECT Cod_Func,
Nome_Func,
Data_Func
FROM Funcionario



Exemplo_02

-- Exibindo os dados de algumas colunas de uma tabela

-- na sequncia desejada


SELECT Data_Func,
Cod_Func,
Nome_Func
FROM Funcionario




5 Exibindo dados de uma tabela utilizando Alias no nome das colunas Demonstrao das
sintaxes disponveis no Microsoft SQL Server




13

Se voc observou os dados retornados pelo SQL Server quando executou qualquer um dos
comandos acima, deve ter observado que ele apresenta a primeira linha resposta com o prprio
nome atribudo cada uma das colunas, que no nosso caso : Cod_Func, Nome_Func, Sexo_Func,
Sal_Func e Data_Func.
normal que os desenvolvedores de banco de dados atribuam nomes abreviados para as
colunas de suas tabelas pois mais fcil trabalhar com nomes curtos ao escrever as queries.
S que isso pode no ficar claro para o usurio que vai utilizar, por exemplo, um relatrio se
voc deixar que estes nomes se apresentem para ele como esto na definio da estrutura da
tabela.
Ns sabemos, por exemplo, o que armazena a coluna Sal_Func, mas para um usu rio pode
ser que no esteja claro que ela representa o salrio de cada funcionrio inserido neste objeto.
Assim sendo, para que possamos gerar relatrios mais claros para nossos usurios podemos
atribuir apelidos para os nomes de cada uma das colunas. Estes apelidos so chamados de Alias e a
Microsoft nos permite escrever os alias de vrias maneiras.


Estas maneiras so exibidas abaixo.



-- Atribuindo apelidos s colunas de uma tabela

-- Primeira sintaxe:

SELECT Cod_Func AS Cdigo,
Nome_Func AS Nome,
Sexo_Func AS Sexo,
Sal_Func AS Salrio,
Data_Func AS Data
FROM Funcionario

--Segunda Sintaxe:

SELECT Cod_Func Cdigo,
Nome_Func Nome,
Sexo_Func Sexo,
Sal_Func Salrio,
Data_Func Data
FROM Funcionario


-- Terceira Sintaxe:



14

SELECT Cdigo = Cod_Func,
Nome = Nome_Func,
Sexo = Sexo_Func,
Salrio = Sal_Func,
Data = Data_Func
FROM Funcionario


-- Quarta sintaxe:

SELECT Cod_Func AS [Cdigo do Funcionario],
Nome_Func AS [Nome do Funcionario],
Sexo_Func AS [Sexo do Funcionario],
Sal_Func AS [Salrio do Funcionario],
Data_Func AS [Data do Funcionario]
FROM Funcionario

-- Quinta Sintaxe:

SELECT Cod_Func AS "Cdigo do Funcionario",
Nome_Func AS "Nome do Funcionario",
Sexo_Func AS "Sexo do Funcionario",
Sal_Func AS "Salrio do Funcionario",
Data_Func AS "Data do Funcionario"
FROM Funcionario


-- Sexta Sintaxe:


SELECT Cod_Func AS 'Cdigo do Funcionario',
Nome_Func AS 'Nome do Funcionario',
Sexo_Func AS 'Sexo do Funcionario',
Sal_Func AS 'Salrio do Funcionario',
Data_Func AS 'Data do Funcionario'
FROM Funcionario


--Stima Sintaxe:

SELECT Cod_Func [Cdigo do Funcionario],
Nome_Func [Nome do Funcionario],
Sexo_Func [Sexo do Funcionario],
Sal_Func [Salrio do Funcionario],


15

Data_Func [Data do Funcionario]
FROM Funcionario


--Oitava Sintaxe:

SELECT Cod_Func "Cdigo do Funcionario",
Nome_Func "Nome do Funcionario",
Sexo_Func "Sexo do Funcionario",
Sal_Func "Salrio do Funcionario",
Data_Func "Data do Funcionario"
FROM Funcionario


--Nona Sintaxe:
SELECT Cod_Func 'Cdigo do Funcionario',
Nome_Func 'Nome do Funcionario',
Sexo_Func 'Sexo do Funcionario',
Sal_Func 'Salrio do Funcionario',
Data_Func 'Data do Funcionario'
FROM Funcionario



-- Dcima Sintaxe:

SELECT [Cdigo do Funcionario] = Cod_Func,
[Nome do Funcionario] = Nome_Func,
[Sexo do Funcionario] = Sexo_Func,
[Salrio do Funcionario] = Sal_Func,
[Data do Funcionario] = Data_Func
FROM Funcionario



-- Dcima primeira Sintaxe:

SELECT "Cdigo do Funcionario" = Cod_Func ,
"Nome do Funcionario" = Nome_Func ,
"Sexo do Funcionario" = Sexo_Func ,
"Salrio do Funcionario" = Sal_Func ,
"Data do Funcionario" = Data_Func
FROM Funcionario




16


-- Decima Sengunda Sintaxe

SELECT 'Cdigo do Funcionario'


= Cod_Func


,

'Nome do Funcionario'

= Nome_Func

,
'Sexo do Funcionario' = Sexo_Func ,

'Salrio do Funcionario'

'Data do Funcionario'

= Sal_Func

= Data_Func

,

FROM Funcionario


Obs.: claro que, apenas na execuo de um nico SELECT, podemos utilizar as sintaxes
exibidas acima misturadas umas com as outras, mas logicamente muito melhor, muito mais
elegante que se tenha um padro para a sua utilizao.


6 Exibindo dados de colunas virtuais



Se voc observar, a tabela Funcionario no possui, em sua estrutura, a coluna
Nacionalidade. Mas suponha que, por um motivo qualquer, voc precise exibir a coluna
Nacionalidade onde nos dados aparece a palavra Brasileira para todos as pessoas inseridas nesta
tabela.
Voc poderia acrescentar esta nova coluna na tabela executando, para tanto, o comando
ALTER TABLE. Mas aqui no o caso. Suponha que voc deseja apenas exibir a nacionalidade
brasileira para todos os funcionrios apenas uma nica vez.
Sendo assim, basta que voc execute um dos comandos abaixo:


-- Exibindo todas as colunas mais uma virtual

SELECT *,'Brasileira' AS Nacionalidade FROM Funcionario



-- Exibindo todas as colunas mais uma virtual

SELECT Cod_Func AS Cdigo,
Nome_Func AS Nome,
Sexo_Func AS Sexo,


17

Sal_Func AS Salrio,
Data_Func AS Data,
'Brasileira' AS Nacionalidade
FROM Funcionario




-- Exibindo algumas colunas e uma virtual

SELECT Cod_Func AS Cdigo,
Nome_Func AS Nome,
Sexo_Func AS Sexo,
'Brasileira' AS Nacionalidade
FROM Funcionario



Obs.: Com relao ao apelido das colunas, obviamente voc poder utilizar, das sintaxes
apresentadas anteriormente, aquela que desejar. Para efeito de demonstrao neste tutorial estamos
utilizando a primeira das sintaxes exibidas no item 3.5.



7 Exibindo clculos em colunas virtuais




Agora vamos supor que voc precise exibir quanto seria o novo salrio de cada funcionrio se
lhes fosse aplicado um aumento de 10% e um aumento salarial de 20%. S que, na realidade, voc
no deseja realmente aplicar o aumento promovendo uma alterao nos dados, voc deseja apenas
visualizar os novos valores.
Sendo assim, voc consegue os resultados desejados escrevendo o comando abaixo.




-- Exibindo aumento de salrio com colunas virtuais



SELECT Cod_Func AS Cdigo,
Nome_Func AS Nome,
Sal_Func AS [Salrio Real],
Sal_Func * 1.1 AS [Salrio com 10%],
Sal_Func * 1.2 AS [Salrio com 20%],
'Brasileira' AS Nacionalidade


18

FROM Funcionario





Observe tambm que possvel exibir colunas virtuais como o caso da nacionalidade e
como o
caso dos
aumentos
salariais
num mesmo
SELECT.


FROM
Funcionario


-- Exibindo aumentos de salrio e a nacionalidade com colunas virtuais



8 Exibindo apenas uma vez os dados repetidos de uma tabela DISTINCT



Para a demonstrao deste tpico, insira os dados abaixo, na tabela Funcionario.



INSERT Funcionario VALUES(6,'Marcia','F',1575.87,Getdate())
INSERT Funcionario VALUES(7,'Paula','F',2500.50,Getdate())
INSERT Funcionario VALUES(8,'Roberto','M',1000.80,Getdate())
INSERT Funcionario VALUES(9,'Cristian','M',578.25,Getdate())
INSERT Funcionario VALUES(10,'Mariana','F',600.00,Getdate())
INSERT Funcionario VALUES(11,'Roberto','M',1000.80,Getdate())
INSERT Funcionario VALUES(12,'Cristian','M',578.25,Getdate())
INSERT Funcionario VALUES(13,'Mariana','F',600.00,Getdate())



Se voc observar, inserimos alguns valores repetidos na tabela Funcionario. Sendo assim,
temos mais de um funcionario com o mesmo nome, mais de um com o mesmo valor salarial e, mais
de um funcionario do sexo feminino, como mais de um do sexo masculino.
Existe uma clusula na liguagem SQL, utilizada com o comando SELECT, que nos permite
exibir apenas uma vez os valores que estiverem repetidos nos dados a serem exibidos.
SELECT Cod_Func

Nome_Func
AS Cdigo,

AS Nome,
Sal_Func

Sal_Func



* 1.1
AS [Salrio Real],

AS [Salrio com 10%],

Sal_Func

'Brasileira'

* 1.2

AS [Salrio com 20%],

AS Nacionalidade



19

Por exemplo, ao executarmos a query abaixo, o SQL Sever nos retornar apenas uma vez a
letra F e apenas uma vez a letra M, muito embora as duas letras tenham sido inseridas vrias
vezes na mesma coluna.



SELECT DISTINCT Sexo_Func FROM Funcionario



A query abaixo exibir apenas uma vez cada valor inserido. Sendo assim considerando, por
exemplo, que o salrio de 2500,00 tenha sido inserido duas vezes na tabela, o comando abaixo
apresentar este valor apenas uma vez.



SELECT DISTINCT Sal_Func FROM Funcionario



A query abaixo exibir apenas uma vez os dados repetidos considerando os valores das
duas colunas sero exibidas.




SELECT DISTINCT Nome_Func,Sal_Func FROM Funcionario




Portanto, quando quiser daber quais os valores existentes em um determinado conjunto de
dados a serem retornados e quiser ver apenas uma vez cada conjunto destes valores, utiliza a
clusula DISTINCT para isso.


UTILIZAO DO COMANDO INSERT



Como voc j deve ter percebido, INSERT o comando da linguagem SQL que utilizamos
para incluir os dados de uma tabela.
Para que voc possa conhecer estas possibilidades de sintaxe da utilizao deste comando
vamos acessar o database [db_Treinamento], e fazer algumas demonstraes, utilizando para
isso, a tabela Funcionario, j criada anteriormente
Para tanto, abra uma nova query no SQL Server Management Studio e em seguida execute
os comandos abaixo, selecionando-os um a um e teclando F5 para cada nova execuo.





20


1 INSERT e INSERT INTO



Quando trabalhamos com a linguagem SQL do Microsoft SQL Server, nos acostumamos a
inserir dados em uma tabela escrevendo apenas a seguinte clusula:




INSERT < NomeTabela > VALUES (valores para cada coluna separados por vrgula).



Acontece que, o comando da linguagem SQL ANSI pra incluso de dados em uma
determinada tabela na verdade INSERT INTO.


INSERT INTO < NomeTabela > VALUES (valores para cada coluna separados por vrgula).



Ento voc j deve ter percebido que a sintaxe SQL da Microsoft nos permite omitir a
clusula INTO na execuo de incluses de dados nas tabelas de um sistema.
Execute os cdigos abaixo e perceba que os dois vo funcionar perfeitamente e inserem os
mesmos dados, do mesmo jeito na tabela Funcionario:


-- INSERT e INSERT INTO


INSERT Funcionario VALUES(1,'Marcos','M',1000.00,Getdate())

GO

INSERT INTO Funcionario VALUES(1,'Marcos','M',1000.00,Getdate())



2 INSERT Posicional e INSERT Declarativo



Chamamos de INSERT Posicional o comando que insere dados em uma tabela passando os
valores para as colunas na mesma ordem em que foram escritas na criao da mesma.
Neste caso no h a necessidade de escrever o nome de cada coluna onde estamos inserindo
os valores, pois presume-se que estamos passando-os na sequncia de sua criao.


Observe o cdigo abaixo:


21




-- Insert Posicional sem a clusula INTO

INSERT Funcionario VALUES(1,'Marcos','M',1000.00,Getdate())


-- Insert Posicional com a clusula INTO

INSERT INTO Funcionario VALUES(1,'Marcos','M',1000.00,Getdate())



J no INSERT Declarativo, como o prprio nome j indica, ns declaramos a ordem das
colunas na qual passaremos os valores durante uma incluso de dados.
Esta forma de escrita do comando INSERT interessante porque nos permite inserir os dados
para as colunas passando os valores na sequncia em que desejarmos, sem a necessidade de
obedecer a order utilizada na criao da tabela.


Observe:

-- Insert Declarativo sem a clusula INTO


INSERT Funcionario (Sexo_Func,Data_Func,Cod_Func,Sal_Func, Nome_Func)

VALUES('M',GETDATE(),1,1000.00,'Marcos')



-- Insert Declarativo com a clusula INTO

INSERT INTO Funcionario (Sexo_Func,Data_Func,Cod_Func,Sal_Func, Nome_Func)

VALUES('M',GETDATE(),1,1000.00,'Marcos')




A utilizao do INSERT Declarativo til quando queremos inserir dados em apenas algumas
colunas da tabela, fazendo com que o SQL Server insira nas colunas restantes valores nulos ou
valores padro (default) se houver algum declarado para estas colunas.

Observe o cdigo abaixo, onde estamos omitindo a incluso de dados para a coluna
Data_Func.




22

INSERT Funcionario (Cod_Func,Sal_Func, Nome_Func) VALUES(1,1000.00,'Marcos')

3 INSERT com uma clusula VALUES



A na verso 2008 do Microsoft SQL Server podemos utilizar a sintaxe abaixo, onde
escrevemos apenas uma vez o comando completo e na sequncia passamos apenas uma lista
de valores que desejamos inserir de uma s vez.

Observe que podemos utilizar ou no a clusula INTO aqui tambm.




INSERT Funcionario VALUES

(1,'Marcos','M',1575.87,Getdate()),

(2,'Paulo','M',2500.50,Getdate()),

(3,'Roberta','F',1000.80,Getdate()),

(4,'Cristina','F',578.25,Getdate()),

(5,'Jos','M',600.00,Getdate())



4 INSERT com SELECT



A composio do comando SELECT com o comando INSERT utilizada para copiar dados
de uma tabela para outra.
Podemos utilizar estes nos comandos nos seguintes casos:

Caso_01 Estruturas iguais

Suponha que voc tenha criado a tabela Empregado, cuja estrutura segue no cdigo abaixo, e
que precise copiar para ela os dados da tabela Funcionario.



CREATE TABLE Empregado
(
Cod_Emp int,
Nome_Emp varchar(100),
Sexo_Emp char(1),


23

Sal_Emp Decimal(10,2),
Data_Emp Datetime,
)


Observando que a estrutura das duas tabelas a mesma, podemos escrever o comando
abaixo para realizar a cpia desejada:



INSERT Empregado SELECT * FROM Funcionario


Caso_02 Estruturas diferentes, com a tabela que recebe os dados tendo menos
colunas que a tabela origem.


Suponha agora qual a tabela para a qual voc deseja copiar dados seja essa cujo cdigo segue
abaixo.



CREATE TABLE Auxiliar
(
Cod_Aux int,
Nome_Aux varchar(100),
Sexo_Aux char(1),
)



Note que neste caso temos que utilizar o comando SELECT, obtendo da tabela Funcionrio
apenas os dados que correspondem s colunas da tabela Auxiliar.


INSERT Auxiliar SELECT Cod_Func,Nome_Func,Sexo_Func FROM Funcionario



Caso_03 Estruturas diferentes, com a tabela que recebe os dados tendo mais colunas
que a tabela origem.


Agora voc tem a tabela Auxiliar, com uma coluna (Nac_Estag Nacionalide do Estagirio)
para a qual no h valor na tabela origem.



CREATE TABLE Estagiario


24

(
Cod_Estag int,
Nome_Estag varchar(100),
Sexo_Estag char(1),
Sal_Estag Decimal(10,2),
Data_Estag Datetime,
Nac_Estag varchar(100),
)


Ento para copiar dados de Funcionario para Estagirio teremos que utilizar um dos
comandos abaixo:


-- Inserindo um catactere em branco na coluna Nac_Estag


INSERT Estagiario SELECT *, ' ' FROM Funcionario


-- Inserindo a palavra Brasileirana coluna Nac_Estag


INSERT Estagiario SELECT *, 'Brasileira' FROM Funcionario



-- Inserindo um valor Nulo na coluna Nac_Estag


INSERT Estagiario SELECT *, Null FROM Funcionario




Poderamos tambm utiilizar a palavra Default no lugar da coluna Nac_Estag, se na
tabelaEstagirio houvesse um valor definido para ela. A sintaxe seria essa:




-- Inserindo o valor Default na coluna Nac_Estag


INSERT Estagiario SELECT *, Default FROM Funcionario




25

Caso_04 Quando a tabela que recebe os dados tem coluna que pode receber Null ou
Default



Neste caso voc utilizaria o INSERT Declarativo para passar os valores desejados.Vamos
Supor que na tabela Estagirio, j haja um valor Default definido para a coluna Nac_Estag e
que voc deseje inserir um valor nulo para a Data_Estag.



Ento seu comando deveria ser escrito assim



-- Inserindo dados na tabela Estagiario, deixando que o prprio SQL Server insira valores nas
colunas Nac_Estag e Data_Estag


INSERT Estagiario (Cod_Estag,Nome_Estag,Sexo_Estag,Sal_Estag) SELECT Cod_Func,
Nome_Func,Sexo_Func,Sal_Func FROM Funcionario



Obs.: Quando inserimos um Null em uma coluna estamos determinando que o SQL Server a
deixe sem valor algum. Portanto Null quer dizer ausncia de valor!



UTILIZAO DO COMANDO UPDATE



UPDATE o comando que utilizamos para modificar os dados em uma ou mais colunas.


1 A clusula SET




Em todo e qualquer comando UPDATE voc dever escrever UMA clusula SET, para se
referenciar a(s) coluna(s) que deseja alterar.



Por exemplo: no script abaixo, estamos criandos uma tabela chamada Pessoa no database
db_Treinamento. Estamos tambm inserindo cinco registros nesta tabela.






26

-----------------------------------------------------------------------

Use db_Treinamento

-----------------------------------------------------------------------

CREATE TABLE Pessoa
(
Cod_Pes
Nome_Pes
Int
varchar(100)

Sexo_Pes

char(1)
Sal_Pes Decimal(10,2)

Data_Pes

Datetime
)
----------------------------------------------------------------------

-- Inserindo dados na tabela Pessoa

INSERT Pessoa VALUES(1,'Marcos','M',1000.00,Getdate())
INSERT Pessoa VALUES(2,'Paulo','M',1000.00,Getdate())
INSERT Pessoa VALUES(3,'Roberta','F',1000.00,Getdate())
INSERT Pessoa VALUES(4,'Cristina','F',1000.00,Getdate())
INSERT Pessoa VALUES(5,'Jos','M',1000.00,Getdate())
----------------------------------------------------------------------



Suponha que voc precise modificar o valor da coluna Sal_Pes aplicando para todas as
pessoas da tabela um aumento salarial de 10%. Para tanto voc teria que escrever um
comando UPDATE. Veja abaixo:


UPDATE Pessoa SET Sal_Pes = Sal_Pes * 1.1


Suponha agora que voc precise modificar os dados da tabela pessoa da seguinte maneira:


a) Acrescente o sobrenome da Silva para todas as pessoas,
b) Altere o valor da coluna Sexo_Pes para X
c) Aplique mais 500.00 de aumento salarial para todos.


O comando UPDATE para este caso tem que ser escrito assim:


27



UPDATE Pessoa SET Nome_Pes = Nome_Pes + 'da Silva', Sexo_Pes = 'x', Sal_Pes =
Sal_Pes + 500.00



2 A clusula FROM


Para o comando UPDATE a clusula FROM opcional. Portanto voc poderia escrever os
UPDATEs anteriores assim, se quisesse:


-----------------------------------------------------------------------

-- Utilizando a clusula FROM

UPDATE Pessoa SET Sal_Pes = Sal_Pes * 1.1 FROM Pessoa

-----------------------------------------------------------------------

UPDATE Pessoa SET Nome_Pes = Nome_Pes + 'da Silva', Sexo_Pes = 'x', Sal_Pes = Sal_Pes
+ 500.00 FROM Pessoa

-----------------------------------------------------------------------

UTILIZAO DO COMANDO DELETE



com o comando DELETE que exclumos dados de uma tabela.


possvel excluir valores de apenas uma coluna? Se esta for tambm a sua dvida, s
pensar que o comando DELETE excluir linhas da tabela. No d para excluir valor de apenas
uma coluna. Podemos sim alterar o valor da mesma, mas quando se trata de DELETE ele retirar da
tabela os valores de uma (ou mais) linha(s) inteira(s)!


1 DELETE com e sem a clsula FROM

Para o comando UPDATE a Microsoft aceita as trs formas de sintaxe abaixo:

-- Excluindo dados da tabela Pessoa

DELETE Pessoa
DELETE Pessoa FROM Pessoa


28

DELETE FROM Pessoa

Obs:


a) DELETE difererente de DROP. O comando DROP elimina objetos de um database.
Por exemplo, se voc executar o comando DROP TABLE Pessoa, estar eliminando a
tabela do database! J o comando DELETE, como visto logo acima, exclui apenas os dados.

b) At este momento, quando utilizamos os comandos SELECT, UPDATE e DELETE, afetamos
todos os registros da tabela. Talvez voc esteja se perguntando como temos que fazer
para ler, alterar e excluir apenas alguns registros da tabela e no todos. Bom, neste caso
voc teria que utilizar a clusula WHERE, que o nosso prximo assunto.


A CLUSULA WHERE



A clusula WHERE utilizada da mesma forma, ou seja, com a mesma sintaxe para os
comandos SELECT, UPDATE e DELETE.
Ela serve para que possamos escolher qual (ou quais) registro(s) da(s) tabela(s) desejamos ler,
alterar ou eliminar.
Para que possamos escolher quais registros desejamos que nosso comando afete vamos
precisar utilizar operadores para fazer a seleo dos mesmos.




1 Operadores e Critrios de Pesquisa


atravs dos operadores que podemos dizer para o SQL Server qual dados deve ser
afetado pelos comandos DML.
Para que possamos fazer demonstraes da utilizao da clusula WHERE vamos executar o
script abaixo, que cria uma tabela chamada Produto, no database db_Treinamento e insere 10
registros de dados.




-----------------------------------------------------------------------

Use db_Treinamento

-----------------------------------------------------------------------


29


CREATE TABLE Produto
(
Cod_Prod int,
Nome_Prod char(50),
Tipo_Prod char(20),
Qtd_Prod int,
Val_Prod decimal(10,2)
)

INSERT Produto VALUES(1,'Geladeira','Cozinha',500,1500.00)
INSERT Produto VALUES(2,'Armrio','Cozinha',700,300.00)
INSERT Produto VALUES(3,'Sof','Sala',200,1200.00)
INSERT Produto VALUES(4,'Cama','Quarto',300,500.00)
INSERT Produto VALUES(5,'Fogo','Cozinha',400,700.00)
INSERT Produto VALUES(6,'Guarda-Roupa','Quarto',500,1000.00)
INSERT Produto VALUES(7,'Poltrona','Sala',600,Null)
INSERT Produto VALUES(8,'Estante','Sala',800,400.00)
INSERT Produto VALUES(9,'Penteadeira','Quarto',200,300.00)
INSERT Produto VALUES(10,'Cadeira','Cozinha',1000,150.00)


Os operadores de comparao so:


Igual (=)


Diferente

(<> ou
!=)


Maior

(>)


Maior ou Igual

(>=)


Menor

(<)


Menou ou Igual (<=)


No Maior

(!>)


No Menor (!<)


Vejamos alguns exemplo:




30


a) Suponha que voc deseje obter os dados da tabela Produto, mas apenas do Produto cujo
cdigo igual a 1. Para tento voc teria que escrever o comando abaixo:

SELECT * FROM Produto WHERE Cod_Prod = 1


b) Se desejasse exibir apenas os dados dos Produtos do tipo Cozinha, teria que escrever o
commando a seguir:


SELECT * FROM Produto WHERE Tipo_Prod = 'Cozinha'


Operadores Lgicos

E (AND
)


Ou

(OR)


Negao (NOT
)


Obviamente possvel escrever mais de uma condio para a clusula WHERE, como no
exemplo abaixo, onde desejamos obter todos os dados do Produto do tipo `Cozinha, mas que
tenham tambm o valor maior do que 500.00.

Para atingir este objetivo escrevemos o comando abaixo:



SELECT * FROM Produto WHERE Tipo_Prod = 'Cozinha' AND Val_Prod > 500.00


Poderamos tambm querer exibir todos os valores dos Produto do tipo Cozinha OU dos
Produtos com valor acima de 500.00.
Para tanto precisaramos escrever o comando abaixo:

SELECT * FROM Produto WHERE Tipo_Prod = 'Cozinha' OR Val_Prod > 500.00



E assim, segue. Se voc precisar, poder colocar quantas condies precisar na clusula
WHERE, sendo que se houver mais de uma, elas devero ser escritas utilizando os operadores
lgicos AND e/ou OR.
Se voc precisasse de todos os produtos que no forem do tipo Cozinha poder| escrever o


31

cdigo abaixo:



SELECT * FROM Produto WHERE Tipo_Prod != 'Cozinha'



Ou poder substitui-lo por este:



SELECT * FROM Produto WHERE Tipo_Prod <> 'Cozinha'


Eu poderia escrever a query abaixo para obter todos os produtos que o valor no seja maior
do que 500.00:



SELECT * FROM Produto WHERE Val_Prod !> 500.00



Eu conseguiria obter os mesmos dados com o comando que segue:




SELECT * FROM Produto WHERE Val_Prod <= 500.00



Suponha que voc queira exibir os dados dos Produtos cujos cdigos sejam 2, 4 e 6. Voc
deseja obter da tabela os trs produtos. Para conseguir isso ter que escrever o cdigo abaixo:




SELECT * FROM Produto WHERE Cod_Prod = 2 OR Cod_Prod = 4 OR Cod_Prod = 6

Operadores para tartar conjunto de valores


Mas com se utilizar o critrio de pesquisa IN poder substituir o cdigo anterior pelo que
segue e conseguir os mesmos dados.



SELECT * FROM Produto WHERE Cod_Prod IN (2,4,6)


Imagine agora que seja necessrio que voc obtenha da tabela todos os Produtos menos os
de cdigo 2, 4 e 6. Pata tanto ter que escrever o cdigo abaixo:


32





SELECT * FROM Produto WHERE Cod_Prod <> 2 AND Cod_Prod <> 4 AND Cod_Prod <> 6




Mas com se utilizar NOT IN poder obter os mesmos valores.




SELECT * FROM Produto WHERE Cod_Prod NOT IN (2,4,6)



Operadores para faixas de Valores



O comando abaixo nos dar todos os produtos cujos valores estejam na faixa de 500.00
e 2000.00 (inclusive os produtos que custarem 500.00 e 2000.00).



SELECT * FROM Produto WHERE Val_Prod >= 500.00 AND Val_Prod <= 2000.00



Os mesmos dados podem ser obtidos utilizando-se o critrio de pesquisa BETWEEEN:



SELECT * FROM Produto WHERE Val_Prod BETWEEN 500.00 AND 2000.00



O comando abaixo nos dar todos os produtos cujo valor estejam fora da faixa de 500.00 e
2000.00:



SELECT * FROM Produto WHERE Val_Prod < 500.00 OR Val_Prod > 2000.00



Os mesmos dados podem ser obtidos utilizando-se os critrios de pesquisa
NOT BETWEEEN:



SELECT * FROM Produto WHERE Val_Prod NOT BETWEEN 500.00 AND 2000.00



Operadores para tartar colunas do tipo charactere


33




Escrevendo o SELECT abaixo obtemos todos os Produtos cujo nome seja exatamente
Geladeira:



SELECT * FROM Produto WHERE Nome_Prod = 'Geladeira'



Porm se desejarmos obter todos os produtos que o nome comece, contenha ou termine
com uma determinada letra ou slaba teremos que utilizar o crtrio de pesquisa LIKE e para
obter os dados negando a existncia dos mesmos critrios, teremos que utilizar NOT LIKE.
Observe exemplos abaixo:



-- Obtendo todos os Produtos cujo nome comea com a legra G.

SELECT * FROM Produto WHERE Nome_Prod LIKE 'G%'


-- Obtendo todos os Produtos que tenha as slabas eira em qualquer posio, incio, meio
ou fim.


SELECT * FROM Produto WHERE Nome_Prod LIKE '%eira%'


-- Selecione todos os Produtos cujo nome termine com a letra O.

SELECT * FROM Produto WHERE Nome_Prod LIKE '%o'

-- Selecione os dados de todos os produtos onde o nome tenha at cinco letras.
Observe que cada letra representada aqui por um tracinho

SELECT * FROM Produto WHERE Nome_Prod LIKE '_____'


-- Selecione todos os Produtos, onde o nome No comece com a letra G,

SELECT * FROM Produto WHERE Nome_Prod NOT LIKE 'G%'



-- Obtendo todos os Produtos que No tenha as slabas eira em qualquer posio, incio,
meio ou fim.



34

SELECT * FROM Produto WHERE Nome_Prod NOT LIKE '%eira%'



-- O exemplo a seguir exibe todos os Produtos cujo nome comece com -- qualquer letra,
contenha a sequncia de letrar ei e contenha logo -- em seguida, qualquer letra,
diferente de a.


SELECT * FROM Produto WHERE Nome_Prod LIKE '%ei_%'ESCAPE 'a'


-- O exemplo abaixo exibe os dados de todos os produtos, cujo nome no Nulo


SELECT * FROM Produto WHERE Nome_Prod IS NOT NULL


-- O exemplo abaixo exibe os dados de todos os produtos, cujo nome Nulo


SELECT * FROM Produto WHERE Nome_Prod IS NULL


Resumo dos Critrios de Avaliao




Critrio Resumo
IN / NOT IN Pesquisa dados em uma tabela com base na
existncia [ou no] dos mesmos em uma lista
de valores,
BETWEEN /NOT BETWEEN Pesquisa dados em uma tabela com base
na existncia [ou no] dos mesmos em uma
faixa de valores.
LIKE / NOT LIKE / SCAPE Pesquisa dados em uma tabela,
verificando sua existncia [ou no] comparando-
os com palavras ou parte delas em uma
determinada coluna. O critrio SCAPE, exclui
uma ou mais letras dos resultados desejados.


35

IS NULL / IS NOT NULL Pesquisa dados em uma tabela com base
na ausncia [ou no] de valores.


Obs.:

a) Todos os exemplos exibidos anteriormente podem ser utilizados com os comandos
UPDATE e DELETE com a mesma sintaxe exibida anteriormente, e podem tambm ser
utilizados para compor um critrio de pesquisa mais complexo:


SELECT * FROM Produto WHERE Nome_Prod LIKE '%A' AND Val_Prod BETWEEN 200.00 AND
500.00 AND Qtd_Prod > 200



UPDATE Produto SET Qtd_Prod = Qtd_Prod - 200.00 WHERE Nome_Prod LIKE '%A' AND
Val_Prod BETWEEN 200.00 AND 500.00 AND Qtd_Prod > 200


DELETE Produto WHERE Nome_Prod LIKE '%A' AND Val_Prod BETWEEN 200.00 AND 500.00
AND Qtd_Prod > 200


b) Podemos utilizar tambm como critrios de pesquisa as funes CONTAINS() e
FREETEXT().




c) Temos tambm a possibilidade de utilizar em clusula WHERE os critrios de pesquisa ALL,
SOME | ANY e EXISTS | NOT EXISTS, mas estes so escritos com subqueries. As
subqueries so vistas no prximo tutorial.



A CLUSULA ORDER BY



A clusula ORDER BY utilizada no comando SELECT com o intuito de exibir dados de
forma ordenada.
A ordenao pode ser feita por uma ou mais colunas, e estas podem estar armazenadas no
formato numrico, caractere, data e data/hora.
Para exemplificar as explicaes sobre esta clausula, vamos criar a tabela Material no
data base db_Treinamento, como mostra o script abaixo:


36



-----------------------------------------------------------------------

Use db_Treinamento

-----------------------------------------------------------------------

CREATE TABLE Material
(
Cod_Mat int,
Tipo_Mat char(1),
Nome_Mat char(50),
Qtd_Mat int,
Val_Mat decimal(10,2)
)

-----------------------------------------------------------------------

INSERT Material VALUES
(1,'A','Caderno Espiral',100,12.50)
(2,'A','Lpis Preto',500,1.50)
(3,'A','Lpis de Cor',600,7.50)
(4,'A','Caneta Azul',800,5.50)
(5,'B','Caneta Preta',150,5.50)
(6,'B','Caderno Brochura',200,10.00)
(7,'B','Borracha Macia',900,5.50)
(8,'B','Borracha Colorida',1000,1.50)
(9,'C','Apontador Colorido',2000,5.50)
(10,'C','Rgua de Madeira',3500,9.00)
(11,'C','Rgua de Plstico',2586,10.00)
(12,'C','Folhas de Papel',2587,5.50)

-----------------------------------------------------------------------



Se voc prestar ateno poder observar que, na coluna Nome_Mat (que representa o nome
dos materiais inseridos na tabela), os dados foram inseridos sem obedecer a nenhuma ordenao
especfica.
Suponha ento que voc precisasse gerar um relatrio que exiba todos os dados da tabela
Material em ordem alfebtica do nome.
Para cumprir com esta tarefa basta escrever e executar o cdigo abaixo:



37

SELECT * FROM Material ORDER BY Nome_Mat



ORDENANDO PELA POSIO DA COLUNA


Podemos ordena os dados a serem exibidos pelo nome da coluna ou pela posio da
mesma em duas situaes.


Ordenando pela posio da coluna na tabela



Observe que a coluna Nome_Mat a terceira coluna da estrutura da tabela Material. Sendo
assim, se voc escrever o comando abaixo, obter os dados na mesma ordenao feita
anteriormente.



SELECT * FROM Material ORDER BY 3

Ordenando pela posico da coluna na lista de colunas do SELECT


O comando abaixo tambm exibe os dados ordenados pela coluna Nome_Mat, que neste
caso a segunda coluna da select list.



SELECT Cod_Mat,Nome_Mat,Val_Mat FROM Material ORDER BY 2


ARGUMENTOS


Podemos utilizar argumetos em cada uma das colunas que escrevermos na clusula ORDER
BY.



ASC Ascendente



Para apresentar os dados ordenados de forma crescente, portanto ascendente, utilizamos o
argumento ASC, que por sinal, j o argumento utilizado como default no SQL Server.



38


SELECT * FROM Material ORDER BY Nome_Mat ASC


SELECT * FROM Material ORDER BY 3 ASC


Portanto escrevendo ASC, ou no, os dados sero apresentados com a mesma ordenao



DESC Decrescente




Para apresentar os dados de forma decrescente utilizamos o argumento DESC.




SELECT * FROM Material ORDER BY Nome_Mat DESC

SELECT * FROM Material ORDER BY 3 DESC




COLLATE



A ordenao feita pelo COLLATE s se aplica s colunas que tenhas os datatypes char,
varchar, nchar e nvarchar.


SELECT * FROM Material ORDER BY Nome_Mat COLLATE Latin1_General_CI_AS_KS_WS


SELECT * FROM Material ORDER BY 3 COLLATE Latin1_General_CI_AS_KS_WS




Obs: Resumidamente falando, collate um conjunto de definies referentes aos dados
armazenados em colunas do tipo caractere. O collation define, por exemplo, que uma coluna
caractere possa armazenar as letras e dgitos referentes um determinado idioma. O Collation
define tambm a forma (binary ou dictionary) em que os dados so ordenados quando um comando
order by executado sobre esta coluna. O Collation tambm define se o SQL Server far diferena,
ou no, entre as letras maisculas e minsculas durante uma pesquisa, define tambm se ele far
diferena entre letras acentuadas ou no.



39



GROUP BY



GROUP BY uma clusula que utilizamos para produzir totalizaes com agrupamentos de
dados.
As totalizaes so feitas atravs das built-on functions Sum(), Count(), Max(), Min(),
Avg(), entre outras e os agrupamentos so feitos com os argumentos HAVING, RULLUP(), CUBE(),
GROUPING SET().
Para exemplificar, execute o script abaixo:



-----------------------------------------------------------------------

USE db_Treinamento

-----------------------------------------------------------------------

DROP TABLE Produto

-----------------------------------------------------------------------

CREATE TABLE Produto
(

Cod_Prod int Not Null,
Cod_Tipo char(1) Not Null,
Cod_Linha tinyint Not Null,
Nome_Prod varchar(50) Not Null,
Qtd_Prod int Not Null,
Val_Prod decimal(10,2) Not Null
)

-----------------------------------------------------------------------

INSERT Produto VALUES(1,'A',1,'Mesa',100,500.00),
(2,'B',1,'Sof',200,1500.00),
(3,'A',2,'Mesa',100,200.00),
(4,'A',2,'Armrio',300,200.00),
(5,'C',1,'Cama',500, 1000.00),
(6,'B',1,'Poltrona',100,250.00),
(7,'B',2,'Sof',200,300.00),


40

(8,'C',2,'Cama',100,150.00),
(9,'A',1,'Armrio',200,800.00),
(10,'C',1,'Guarda-Roupa',100,1500.00)

-----------------------------------------------------------------------




FUNES DE TOTALIZAO

FUNO O QUE FAZ EXEMPLO DE USO
AVG() Retorna a mdia dos valores de
uma Expresso Numrica
Avg(ExpressoNumrica)
COUNT() Retorna o nmero de linha com
o contedo diferente de Null. O
seu retorno estar no formato int.
Count(ExpressoNumrica)
COUNT(*) Retorna o nmero total de
linhas considerando os valores
nulos. O seu retorno estar no
formato int.
Count(*)
COUNT_BIG
()
Retorna o nmero de linha com
o contedo diferente de Null. O
seu retorno estar no formato Bigint.
COUNT_BIG(ExpressoNu
mrica)
COUNT_BIG
(*)
Retorna o nmero total de
linhas considerando os valores
nulos. O seu retorno estar no
formato Bigint.
COUNT_BIG(*)
MAX() Retorna o maior valor de uma coluna Max(ExpressoNumrica)
MIN() Retorna o menor valor de uma coluna Min(ExpressoNumrica)
STDEV Retorna o desvio padro de uma
expresso numrica. (Clculo
Estatstico)
Stdev (ExpressoNumrica)


41























UTILIZANDO GROUP BY



No nosso primeiro exemplo queremos mostrar a quantidade de produtos em estoque que
temos para cada tipo de produto. Para tanto temos que executar o seguinte comando:



SELECT Cod_Tipo, Sum(Qtd_Prod) AS Qtd_Prod FROM Produto GROUP BY Cod_Tipo



Se quisssemos exibir o total de produtos em estoque por tipo e por linha de produto
teramos que executar o cdigo abaixo:




SELECT Cod_Tipo,Cod_Linha, Sum(Qtd_Prod) AS Qtd_Prod FROM Produto GROUP BY
Cod_Tipo,Cod_Linha



HAVING



Se quisessemos restringir o resultado apresentado no primeiro exemplo acima, ou seja, se
STDEVP() Retorna o desvio padro
populacional de uma expresso
numrica. (Clculo Estatstico)
Dtdevp(ExpressoNumrica
)
VAR() Retorna a variao estatstica de
uma expresso numrica.(Clculo
Estatstico)
Var(ExpressoNumrica)
VARP() Retorna a variao estatstica
populacional de uma expresso
numrica. (Clculo Estatstico)
Varp(ExpressoNumrica)
GROUPING(
)
Cria uma nova coluna no resultado
de um SELECT com as clusulas
GROUP BY / CUBE ou GROPUP
BY/ROLLUP. A funo acrescenta o
nmero 1 se o valor for resultado de
uma totalizao e 0 se o valor no for
resultado de uma totalizao.
Grouping(ExpressoNumri
ca)


42

quisessemos exibir a quantidade total em estoque dos produtos agrupador por tipo, mas desejando
apresentar s os dados onde a soma das quantidades em estoque seja maior do que 500, teramos
que utilizar a clusula HAVING, como segue:




SELECT Cod_Tipo, Sum(Qtd_Prod) AS Qtd_Prod FROM Produto GROUP BY Cod_Tipo
HAVING Sum(Qtd_Prod) > 500


CASE



A clusula CASE utilizada quando desejamos executar testes de condio dentro de
uma query.


Para fazermos nossas demonstraes, execute o cdigo abaixo:



-----------------------------------------------------------------------

db_Treinamento

-----------------------------------------------------------------------

DROP TABLE Cliente

go

-----------------------------------------------------------------------


CREATE TABLE Cliente
(
Cod_Cli int,
Nome_Cli varchar(100),
Est_Civil char(1),
Renda_Cli decimal(10,2),
Nome_Cid varchar(100)
)


-----------------------------------------------------------------------




43

INSERT Cliente VALUES
(1,'Jos Maria','C',1500.00,'So Paulo')
(2,'Maria Jos','S',2500.00,'So Paulo')
(3,'Jos','D',5300.00,'Sorocaba')
(4,'Maria','S',6500.00,'Jundia')
(5,'Ana','C',7600.00,'So Jos do Rio Preto')
(6,'Anita','C',500.00,'Araraquara')
(7,'Paulo','S',2500.00,'So Carlos)
(8,'Paula','S',1500.00,'So Paulo')
(9,'Roberto','V',3500.00,'So Paulo')
(10,'Roberta','S',4500.00,'So Paulo')

-----------------------------------------------------------------------
CASE COM SELECT



fcil perceber o que a query abaixo vai exibir. Na tabela, na coluna Est_Civil (Estado Civil)
ns inserimos as letras S,C,D,V para (Solteiro, Casado, Divorsiado e Vivo).
No relatrio que precisamos gerar, temos que fazer aparecer as palavras relativas ao
estado civil de cada cliente e no as letras. No desejamos modificar os dados e nem a estrutura da
tabela, apenar queremos o relatrio.
Para tanto, execute o cdigo abaixo:


SELECT CASE Est_Civil
WHEN 'S' THEN 'Solteiro'
WHEN 'C' THEN 'Casado'
WHEN 'D' THEN 'Divorsiado'
WHEN 'V' THEN 'Vivo'
ELSE 'Estado Civil inexistente'
END AS [Estado Civil]
FROM Cliente



-------------------------------------------------------------------


SELECT CASE

WHEN Est_Civil = 'S' THEN 'Solteiro'

WHEN Est_Civil = 'C' THEN 'Casado'



44

WHEN Est_Civil = 'D' THEN 'Divorsiado'

WHEN Est_Civil = 'V' THEN 'Vivo'

ELSE 'Estado Civil inexistente'

END AS [Estado Civil]

FROM Cliente




-------------------------------------------------------------------




Note que temos duas opes de sintaxe para a utilizao da clusula CASE. A primeira
escreve uma nica vez o nome da coluna Est_Civil e a segunda escreve-a vrias vezes, uma para
cada WHEN.
H casos, como este, em que tanto faz voc utilizar a primeira como a segunda sintaxe, s
que no caso da necessidade de se fazer comparaes um pouco mais complexas temos que utilizar
a segunda sintaxe. Um exemplo disso o que mostramos abaixo:




SELECT Nome_Cli, CASE WHEN Renda_Cli <= 1000 THEN 'Crdito de 500.00' WHEN Renda_Cli
Between 1000 And 2000 THEN 'Crdito de 800.00' ELSE 'Credito Aprovado' END AS Crdito
FROM Cliente

Como temos que comparar a Renda_Cli com uma faixa de valores, temos que optar pela
segunda forma de se escrever este comando.




CASE COM ORDER BY



Podemos utilizar a clusula CASE tambm como uma opo no ORDER BY.



-- Para os clientes que tm como salrio um valor <= 1000 os dados so
apresentados ordenados pelo Nome_Cli de forma Decrescente Para os salrios que forem
inferiores a 1000.00 os dados so apresentados ordenados de forma crescente tambm pelo
Nome_Cli



45


SELECT Cod_Cli,Nome_Cli,Sal_Cli FROM Cliente ORDER BY CASE Renda_Cli <= 1000.00
THEN Nome_Cli END DESC, CASE Renda_Cli < 1000.00 THEN Nome_Cli END ASC



-----------------------------------------------------------------------



-- Apresenta os dados ordenados pela coluna Nome_Cid quando o Sexo do cliente for 'F',
caso contrrio apresenta os dados ordenados pelo Nome_Est




SELECT Cod_Cli,Nome_Cli,Sal_Cli FROM Cliente ORDER BY CASE Sexo_Cli WHEN 'F' THEN
Nome_Cid ELSE Nome_Est END




CASE COM UPDATE



Muitas vezes precisamos fazer alteraes nos dados com base em condies, como no caso
de aplicar um aumento na renda do cliente. Se o cliente for do sexo feminino o aumento dever
ser de 20% e se for do sexo masculino dever ser de 10%.

UPDATE Cliente
SET Renda_Cli = CASE Sexo_Cli = 'F' THEN Renda_Cli * 1.2
ELSE Renda_Cli * 1.1
END
END




Abaixo temos uma variao do mesmo comando, apenas acrescentamos a clusula
OUTPUT, para exibir os dados como eles eram antes da alterao.


UPDATE Cliente
SET Renda_Cli = CASE Sexo_Cli = 'F' THEN Renda_Cli * 1.2
ELSE Renda_Cli * 1.1
END
END
OUTPUT DELETED.*
WHERE Nome_Cid = 'So Paulo'


46




CASE COM HAVING



Tambm podemos restringir os dados de um agrupamento que sero apresentados
utilizando a clusula CASE juntamente com HAVING.


-- Exibe os valores das rendas dos clientes totalizando-as por Sexo_Cli Se o cliente for do
sexo = 'F' apenas os dados com Renda_Cli > 500.00 sero considerados Se o cliente for do
sexo = 'M' apenas os dados com Renda_Cli > 1000.00 sero considerados


SELECT Sexo_Cli, Sum(Renda_Cli)
FROM Cliente
GROUP BY Sexo_Cli
HAVING (Sum(CASE Sexo_Cli = 'F' THEN Renda_Cli END) > 500.00
OR Sum(CASE Sexo_Cli = 'M' THEN Renda_Cli END) > 1000.00)
-----------------------------------------------------------------------
A CLUSULA UNION



Muitas vezes precisamos exibir dados de vrias tabelas transformando-os em um nico
conjunto de informao. Para tanto, temos alguns comandos que podem ser utilizados, dependendo
obviamente, de como precisamos exibir a informao.
Para esta demonstrao execute o script abaixo:


-----------------------------------------------------------------------


USE db_Treinamento

-----------------------------------------------------------------------


CREATE TABLE Aluno
(
Cod_Alu int ,
Nome_Alu varchar(100),
Ida_Alu tinyint
)



47

INSERT Aluno VALUES(1,'Maria',10)
INSERT Aluno VALUES(2,'Rita',7)


-----------------------------------------------------------------------


CREATE TABLE Professor
(
Cod_Prof int,
Nome_Prof varchar(100),
RG_Prof char(12)
)

INSERT Professor VALUES(1,'Ricardo','155822')
INSERT Professor VALUES(2,'Roberto','152856')

-----------------------------------------------------------------------
CREATE TABLE Mestre
(
Cod_Mestre int,
Nome_Mestre varchar(100),
DtCad_Mestre datetime,
Sal_Mestre decimal(10,2)
)

INSERT Mestre VALUES(1,'Paulo',Getdate(),10000.00)
INSERT Mestre VALUES(2,'Paula',Getdate(),15000.00)


-----------------------------------------------------------------------



UNION



Precisamos exibir os dados das tabelas Aluno, Professor e Mestre em um nico conjunto
de resultado.
Utilizando a clusula UNION podemos conseguir atingir este objetivo. Observe:

-----------------------------------------------------------------------




48

SELECT Cod_Alu AS Cdigo,
Nome_Alu AS Nome,
'Aluno' AS Tipo,
Ida_Alu AS Idade,
' ' AS RG,
null AS Data
FROM Aluno
UNION
SELECT Cod_Prof,
Nome_Prof,
'Professor',
0,
RG_Prof,
null
FROM Professor
UNION
SELECT Cod_Mestre,
Nome_Mestre,
'Mestre',
0,
' ',
DTCad_Mestre
FROM Mestre


-----------------------------------------------------------------------



Note que a utilizaao da cusula UNION tem algumas regras:



a) Todos os SELECTs utilizados devero apresentar a mesma quantidade de colunas e seus
datatypes devem ser correspondentes entre si, ou seja, o tipo de dados da primeira coluna do
primeiro SELECT tem que ser o mesmo tipo da primeira coluna do segundo SELECT e do terceiro.
O tipo de dado da segunda coluna deve ser o mesmo para todas as segundas colunas de
todos os SELECTs envolvidos no relatrio a ser gerado.

b) O Apelido para as colunas deve ser posto apenas no primeiro SELECT.


c) Cada SELECT pode ser escrito com JOIN, Subqueries, GROUP BY e WHERE.


d) Se desejarmos ordenar o conjunto de dados a clusula ORDER BY deve ser escrita no final,


49

em ltimo lugar.



UNION ALL



H uma diferena entre UNION e UNION ALL. Utilizando apenas a clusula UNION, se por
acaso, houver os mesmos dados em mais de uma tabela, o SQL Server os apresentar
apenas uma vez. Utilizando UNION ALL todas as linhas de dados sero exibidas, mesmo que haja
repeties.

Valem para UNION ALL, as mesmas regras do UNION.


SELECT Cod_Alu AS Cdigo,
Nome_Alu AS Nome,
'Aluno' AS Tipo,
Ida_Alu AS Idade,
' ' AS RG,
null AS Data
FROM Aluno
UNION ALL
SELECT Cod_Prof,
Nome_Prof,
'Professor',
0,
RG_Prof,
null
FROM Professor
UNION ALL
SELECT Cod_Mestre,
Nome_Mestre,
'Mestre',
0,
' ',
DTCad_Mestre
FROM Mestre




GROUPING SETS()


50




GROUPING SETS() uma clusula nova que pode ser substituir o UNION ALL, com uma
performance melhor, nestes casos:




SELECT Count(Cod_Mestre) FROM Mestre
UINON ALL
SELECT Avg(DTCad_Mestre) FROM Mestre
UNION ALL
SELECT Sum(Sal_Mestre) FROM Mestre



-----------------------------------------------------------------------




Em vez de escrever tres queries nas mesma tabela como mostra o comando acima, utilize
GROUPING SETS() como segue:




-- O SQL Server 2008 nos permite obter os mesmos dados acima com uma melhor
performance, escrevendo a query utilizando as clusulas GROUPING SETS()




SELECT Count(Cod_Mestre), Avg(DTCad_Mestre),Sum(Sal_Mestre)
FROM Mestre
GROUP BY GROUPING SETS((Cod_Mestre),(DTCad_Mestre),(Sal_Mestre)())




INTERSECT E EXCEPT



INTERSECT a clusula que utilizamos para obter dados que fazem parte de duas tabelas ao
mesmo tempo (interseco).


EXCEPT a clusula que utilizamos para obter dados que existem em uma tabela e no
existem em outra.




51

Observe o contedo das duas clusulas (INTERSECT e EXCEPT):


----------------------------------------------------------------------


CREATE TABLE Mestre_Historico
(
Cod_Mestre int,
Nome_Mestre varchar(100),
DtCad_Mestre datetime,
Sal_Mestre decimal(10,2)
)
INSERT Mestre_Historico VALUES(1,'Paulo',Getdate(),10000.00)
INSERT Mestre_Historico VALUES(1000,'Ricardo',Getdate(),10000.00)

----------------------------------------------------------------------

-- INTERSECAO: O que tem igual nas duas tabelas

-- Aparecer apenas os dados do Paulo, cujo cod_Mestre igual a 1

SELECT * FROM Mestre
INSERSECT
SELECT * FROM Mestre_Historico

---------------------------------------------------------------------

-- EXCEO: O que tem em uma tabela e no tem na outra

-- Exibe apenas o que tem em Mestre e no tem no Mestre_Historico

-- Aparecer s os dados do mestre de cdigo 2, chamado Paula.

SELECT * FROM Mestre

EXCEPT

SELECT * FROM Mestre_Historico

---------------------------------------------------------------------

-- Exibe apenas o que tem em Mestre_Historico e no tem no Mestre

-- Aparecer s os dados do mestre de cdigo 1000, chamado Ricardo.



52

SELECT * FROM Mestre_Historico

EXCEPT

SELECT * FROM Mestre
---------------------------------------------------------------------
JOINS TRANSFORMANDO DADOS EM INFORMAO



Associar uma ou mais tabelas o mesmo que liga-las atravs de uma ou mais colunas que
elas tenham em comum, com o objetivo de obter dados relacionado entre estas tabelas em questo.
Existem algumas formas de associar dados dependendo do resultado que se deseja obter:




INNER JOIN ou JOIN - Apenas dados Relacionados

Natural-Join

Equi-Join

Self Join




OUTER JOIN Dados Relacionados e no Relacionados

Left Outer Join ou Left Join

Right Outer Join ou Right Join

Full Outer Join ou Full Join




CROSS JOIN Produto Cartesiano




Suponha que voc tenha uma tabela chamada Pai e uma tabela chamada Filho com a
estrutura e dos dados apresentados logo abaixo:



CREATE TABLE Pai
(
Cod_Pai int identity not null Primary Key,


53

Nome_Pai char(30) not null,
Idade_Pai tinyint not null
)


CREATE TABLE Filho
(
Cod_Filho int identity not null Primary Key,
Cod_Pai int not null References Pai(Cod_Pai),
Nome_Filho char(30) not null,
Sexo_Filho char(01) not null Check(Sexo_Filho IN (F,M))
)


PAI
Cod_Pai Nome_Pai Idade_Pai
1 Daniel de Souza Leo Sobrinho 62
2 Agnaldo Diogo dos Santos 38
3 Fernando de Oliveira Leo 36





FILHO
Cod_Filho Cod_Pai Nome_Filho Sexo_Filho
1 1 Renata de Oliveira Leo F
2 1 Fernando de Oliveira Leo M
3 1 Roberta de Oliveira Leo F
3 1 Jairo de Oliveira Leo M
4 2 Bruno Ferreira dos Sandos M
5 2 Antonio dos Santos Neto M
6 2 Pedro Ferreira dos Santos M


54

7 3 Lucar Ribeiro Leo M
8 3 Helder Riberito Leo M
9 4 Mateus Ribeiro Leo M


Voc poderia associar estas tabelas atravs da a Cod_Pai (coluna que comum s
duas tabelas) para obter dados relacionados de diversas formas:




INNER JOIN



A clusula INNER JOIN tem como objetivo selecionar de duas ou mais tabelas apenas os
dados relacionados entre todas elas. Um INNER JOIN poder ser:
- Um Natural Join ou

- Um Equi Join



INNER JOIN NATURAL JOIN



Suponha que voc precise obter o nome de todos os Pais e o nome e o sexo de todos os
filhos que cada pai possui (observe os dados abaixo):


Nome do Pai Nome do Filho Sexo
Daniel de Souza Leo Sobrinho Renata de Oliveira Leo F
Daniel de Souza Leo Sobrinho Fernando de Oliveira Leo M
Daniel de Souza Leo Sobrinho Roberta de Oliveira Leo F
Daniel de Souza Leo Sobrinho Jairo de Oliveira Leo M
Agnaldo Diogo dos Santos Bruno Ferreira dos Santos M


55

Agnaldo Diogo dos Santos Antonio dos Santos Neto M
Agnaldo Diogo dos Santos Pedro Ferreira dos Santos M
Fernando de Oliveira Leo Lucas Ribeiro Leo M
Fernando de Oliveira Leo Helder Ribeiro Leo M
Fernando de Oliveira Leo Mateus Ribeiro Leo M


Para conseguir esta resposta ser necessrio relacionar as duas tabelas. Note que estas duas
tabelas se relacionam pela coluna Cod_Pai. Isto quer dizer que as duas tabelas tm a coluna
Cod_Pai e que elas possuem os mesmos valores.
Se voc observar tambm, esta coluna comum s duas tabelas, a chave primria da tabela
Pai e a chave estrangeira na tabela Filho. Para obter os dados desejados execute o seguinte
comando:


SELECT Pai.Nome_Pai as [Nome o Pai], Filho.Nome_Filho as [Nome o Filho],
Filho.Sexo_Filho as Sexo FROM Pai INNER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai


IMPORTANTE: Observe que, para executar o comando acima, no necessrio que as
tabelas tenham as constraints Primary Key e Foreign Key, basta que as colunas que relacionam as
duas tabelas sejam do mesmo datatype. Para que a resposta que voc vai obter faa sentido
para o seu sistema os dados tm que estar relacionados, ou seja, todos os filhos tm que ter um pai
existente na tabela pai. Obviamente as constraints garantem que os dados obtidos como resposta
so vlidos, porque elas no permitiro que sejam executadas operaes que provoquem
inconsistncias nos mesmos.


o EQUI JOIN




Este INNER JOIN abaixo, que retorna todas as linhas relacionadas de duas tabelas e
apresenta todas as colunas das tabelas evolvidas no comando conhecido como Equi-Join porque
apresentar, por exemplo, dados repetidos na coluna Cod_Pai (que existe nas duas tabelas).




SELECT * FROM Pai INNER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai


Se voc selecionar no seu comando com INNER JOIN apenas colunas que no se repetem, este


56

INNER JOIN ser um Natural-Join:




SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho],
Filho.Sexo_Filho as Sexo FROM Pai INNER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai



o SELF JOIN




Self Join um Inner Join de uma tabela consigo mesma. Este tipo de join apresenta dados de
um auto-relacionamento.


O auto-relacionamento acontece quando uma determinada chave estrangeira de uma tabela
est relacionada com a chave primria da mesma tabela. Observe o caso da tabela
funcionrio apresentada a seguir:




CREATE TABLE Funcionario

(

Cod_Func int not null,

Nom_Func char(10) not null,

Cod_Chefe int null,

Constraint PK_Func Primary Key(Cod_Func),

Constraint FK_Func Foreign Key(Cod_Chefe) References (Cod_Func)

)



Note que o comando acima coloca uma chave primria na coluna Cod_Func e a
chave estrangeira, que colocada na coluna Cod_Chefe, faz referncia a coluna Cod_Func.
A tabela Funcionrio armazena dados do Funcionrio e o seu Chefe, sendo que um chefe
s poder ser chefe se for antes um funcionrio.
Se voc observar, a coluna Cod_Chefe aceita valores nulos, para que voc possa inserir


57

funcionrios que no tenham chefe algum, ou que sejam seu prprio chefe.



Veja a tabela com dados:



Cod_Func Nom_Func Cod_Chefe
1 Joo NULL
2 Matheus 1
3 Lucas 1
4 Pedro 2
5 Thiago 2
6 Jos 2
7 Tnia 1
8 Joana 3
9 Rosana 3
10 Maria 4



Voc oportunidade, em tpicos anteriores, de aprender a colocar Alias na colunas das
tabelas em um Select para obter dados com uma visualizao mais amigvel, ou seja para poder
visualizar as colunas com um ttulo diferente do armazenado na tabela.
Para fazer o Self Join voc precisa tambm saber escrever o alias de tabela. Isto bem
simples:




SELECT F.Cod_Func,

F.Nom_Func,

F.Cod_Chefe



58

Chefe Funcionrio
Joo Matheus
Joo Lucas
Joo Tania
Lucas Joana
Lucas Rosana
Matheus Jos
Matheus Pedro
Matheus Thiago

FROM Funcionario F




Muito embora no seja necessrio utilizar o alias de tabela no Select apresentado acima, a
letra F o alias de tabela.
Para obter como resposta o nome de todos os funcionrios e de seus chefes voce dever
escrever o comando abaixo, que associa a tabela Funcionrio com ela mesma:




SELECT A.Nom_Func as Chefe,

B.Nom_Func as Funcionario

FROM Funcionario A inner join Funcionario B

ON A.Cod_Func = B.Cod_Chefe

ORDER BY 1



Note que o self join escrito acima associa a tabela Funcionrio com ela mesma, utilizando
para isso as letras A e B para fazer o alias de tabela. O join associa as duas tabelas A e B
atraves das colunas Cod_Func e Cod_Chefe.
Note tambm que alm de utilizar o alias de tabela foi utilizado alias de coluna para facilitar a
compreeno dos dados.
Ao executar o comando anterior voc obtm a seguinte resposta:


















59












LEFT JOIN




Utilizando novamente o exemplo do relacionamento entre as tabela Pai e Filho, observe
que na tabela pai agora existe um pai para o qual no foi registrado nenhum filho na tabela Filho.
Esta situao no representa um erro, porque necessrio registrar primeiro o pai para depois
inserir seus filhos. Neste caso, suponha que voc inseriu o Pai cujo cdigo o nmero 4 e que ainda
no colocou nenhum filho para ele. Observe a demonstrao abaixo:




















FILHO
Cod_Filho Cod_Pai Nome_Filho Sexo_Filho
1 1 Renata de Oliveira Leo F
2 1 Fernando de Oliveira Leo M
PAI
Cod_Pai Nome_Pai
1 Daniel de Souza Leo Sobrinho
2 Agnaldo Diogo dos Santos
3 Fernando de Oliveira Leo
4 Jairo de Oliveira Leo


60

3 1 Roberta de Oliveira Leo F
3 1 Jairo de Oliveira Leo M
4 2 Bruno Ferreira dos Santos M
5 2 Antonio dos Santos Neto M
6 2 Pedro Ferreira dos Santos M
7 3 Lucas Ribeiro Leo M

8 3 Helder Ribeiro Leo M
9 3 Mateus Ribeiro Leo M


Para que voc possa exibir os dados de todos os pais relacionando estes dados com os
respectivos filhos, mostrando tambm os dados dos pais que ainda esto sem filhos registrados,
escreva o seguinte comando:


SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Filho.Sexo_Filho as
Sexo FROM Pai LEFT OUTER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai


A clusula LEFT est sendo utilizada para mostrar todos os dados da tabela escrita do lado
esquerdo do join. O conjunto resposta obtido com a execuo do comando acima este:



Nome do Pai Nome do Filho Sexo
Daniel de Souza Leo Sobrinho Renata de Oliveira Leo F
Daniel de Souza Leo Sobrinho Fernando de Oliveira Leo M
Daniel de Souza Leo Sobrinho Roberta de Oliveira Leo F
Daniel de Souza Leo Sobrinho Jairo de Oliveira Leo M
Agnaldo Diogo dos Santos Bruno Ferreira M
Agnaldo Diogo dos Santos Antonio dos Santos Neto M


61


Agnaldo Diogo dos Santos Pedro Ferreira dos Santos M
Fernando de Oliveira Leo Lucar Ribeiro Leo M
Fernando de Oliveira Leo Helder Ribeiro Leo M
Fernando de Oliveira Leo Mateus Ribeiro Leo M


Note que o SQL Server relacionou os dados como fez no caso do INNER JOIN, mas no caso
do LEFT JOIN especificamente, mostrou tambm os dados da tabela Pai (tabela que foi escrita do
lado esquerdo das palavras LEFT OUTER JOIN) que no se relacionaram com nenhum filho.
Se voc precisasse obter como resposta apenas os dados dos pais para os quais voc ainda
no inseriu nenhum filho bastaria acrescentar ao comando a clusula WHERE como segue:




SELECT Pai.* FROM Pai LEFT OUTER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai WHERE
Filho.Nome_Filho IS NULL



RIGHT JOIN


Em uma outra situao, suponha que por algum motivo, foi necessrio inserir alguns filhos
na tabela Filho, para um pai que no existe na tabela Pai. Ento, para fazer isso, voc desligou a
constraint de chave estrangeira, inseriu os dados inconsistentes e religou a chave estrangeiras
dizendo para o SQL Server no checar dados j existentes.
Suponha, ento, que seus dados ficaram desta forma:



















PAI
Cod_Pai Nome_Pai
1 Daniel de Souza Leo Sobrinho
2 Agnaldo Diogo dos Santos
3 Fernando de Oliveira Leo
4 Jairo de Oliveira Leo


62




FILHO
Cod_Filho Cod_Pai Nome_Filho Sexo_Filho
1 1 Renata de Oliveira Leo F
2 1 Fernando de Oliveira Leo M
3 1 Roberta de Oliveira Leo F
3 1 Jairo de Oliveira Leo M
4 2 Bruno Ferreira dos Santos M
5 2 Antonio dos Santos Neto M
6 2 Pedro Ferreira dos Santos M
7 3 Lucas Ribeiro Leo M
8 3 Helder Ribeiro Leo M
9 3 Mateus Ribeiro Leo M
10 1000 Sandra Rosa Madalena F
11 1000 Margarida Paula Regina F
12 1000 Ana Maria Cristina F



Os trs ltimos filhos pertencem a um pai cujo cdigo o nmero 1000 e este pai no existe
na tabela Pai.
Se voc precisasse obter como resposta os dados dos filhos e seus pais, mostrando inclusive
os filhos rfos, voc precisaria escrever o seguinte comando:


SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Filho.Sexo_Filho as
Sexo FROM Pai RIGHT OUTER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai


Nome do Pai Nome do Filho Sexo


63

Daniel de Souza Leo Sobrinho Renata de Oliveira Leo F
Daniel de Souza Leo Sobrinho Fernando de Oliveira Leo M
Daniel de Souza Leo Sobrinho Roberta de Oliveira Leo F
Daniel de Souza Leo Sobrinho Jairo de Oliveira Leo M
Agnaldo Diogo dos Santos Bruno Ferreira M
Agnaldo Diogo dos Santos Antonio dos Santos Neto M
Agnaldo Diogo dos Santos Pedro Ferreira dos Santos M
Fernando de Oliveira Leo Lucar Ribeiro Leo M
Fernando de Oliveira Leo Helder Ribeiro Leo M
Fernando de Oliveira Leo Mateus Ribeiro Leo M
Null Sandra Rosa Madalena F
Null Margarida Paula Regina F
Null Ana Maria Cristina F




Se voc precisasse obter como resposta apenas os dados dos filhos para os quais voc no
inseriu nenhum pai, voc poderia escrever o comando assim:



SELECT Filho.* FROM Pai RIGHT OUTER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai WHERE
Pai.Cod_Pai IS NULL



FULL JOIN


possvel que voc precise ler, em apenas uma resposta, todos os dados relacionados e no
relacionados. Suponha que voc precise ento dos seguintes dados:


Nome do Pai Nome do Filho Sexo
Daniel de Souza Leo Sobrinho Renata de Oliveira Leo F


64

Daniel de Souza Leo Sobrinho Fernando de Oliveira Leo M
Daniel de Souza Leo Sobrinho Roberta de Oliveira Leo F
Daniel de Souza Leo Sobrinho Jairo de Oliveira Leo M
Agnaldo Diogo dos Santos Bruno Ferreira M
Agnaldo Diogo dos Santos Antonio dos Santos Neto M
Agnaldo Diogo dos Santos Pedro Ferreira dos Santos M
Fernando de Oliveira Leo Lucar Ribeiro Leo M
Fernando de Oliveira Leo Helder Ribeiro Leo M
Fernando de Oliveira Leo Mateus Ribeiro Leo M
Jairo de Oliveira Leo NULL NULL
Null Sandra Rosa Madalena F
Null Margarida Paula Regina F
Null Ana Maria Cristina F

O comando que dever ser escrito para que voc receba estes dados como resposta esse:


SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Filho.Sexo_Filho
as Sexo FROM Pai FULL OUTER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai


Se voc precisasse obter como resposta apenas os dados no relacionados voc poderia
escrever o comando assim:

SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Filho.Sexo_Filho
as Sexo FROM Pai FULL OUTER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai WHERE
Pai.Cod_Pai IS NULL OR Filho.Cod_Pai IS NULL
CROSS JOIN


o produto cartesiano. O Cross Join relaciona todas as linhas da tabela A com todas as
linhas da tabela B. Observe o exemplo a seguir:


Material
Cod_Mat Mome_Mat


65

PAI
Cod_Pai Nome_Pai
1 Daniel de Souza Leo Sobrinho
2 Agnaldo Diogo dos Santos
3 Fernando de Oliveira Leo
4 Jairo de Oliveira Leo

1 Caderno
2 Lpis
3 Borracha
4 Caneta


Pedido
Num_Ped Data_Pe
d 1 24/06/2009
2 06/08/2009


De acordo com os dados acima, execute estes comandos:


SELECT Pedido.Num_Ped, Material.Nome_Mat FROM Pedido CROSS JOIN Material


Os dados que voc obtm como resposta so os seguintes:


Num_Ped Cod_Ma
t 1 Caderno
1 Lpis
1 Borracha
1 Caneta
2 Caderno
2 Lpis
2 Borracha
2 Caneta


Em todos os pedidos foram vendidos uma determinada quantidade de todos os materiais.
JOIN COM MAIS DE DUAS TABELAS


Agora voc deve supor que no seu sistema existam estas trs tabelas:














66












FILHO
Cod_Filh
o
Cod_Pai Nome_Filh
o
Sexo_Filho
1 1 Renata de Oliveira Leo F
2 1 Fernando de Oliveira Leo M
3 1 Roberta de Oliveira Leo F
3 1 Jairo de Oliveira Leo M
4 2 Bruno Ferreira dos Santos M
5 2 Antonio dos Santos Neto M
6 2 Pedro Ferreira dos Santos M

7 3 Lucas Ribeiro Leo M
8 3 Helder Ribeiro Leo M
9 3 Mateus Ribeiro Leo M
10 1000 Sandra Rosa Madalena F
11 1000 Margarida Paula Regina F
12 1000 Ana Maria Cristina F

NOTAS
Num_Lanc Cod_Filho Nota_Filho
1 1 10,00
2 1 9,00
3 1 10,00
4 2 8,00
5 2 7,00


67































SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Nota.Nota_Filho
as [Nota do Filho] FROM Pai INNER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai INNER JOIN Nota
ON Filho.Cod_Filho = Nota.Cod_Filho


Para processar este comando, o SQL Server faz o Join entre a tabela Pai e Filho, e deste
conjunto resultante faz o join com a tabela Nota.


SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Nota.Nota_Filho
as [Nota do Filho] FROM Pai INNER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai LEFT JOIN Nota
ON Filho.Cod_Filho = Nota.Cod_Filho


O comando acima mostra todos os pais e seus filhos e as notas destes filhos, mostra
inclusive os filhos sem nota.


SELECT Pai.Nome_Pai as [Nome do Pai], Filho.Nome_Filho as [Nome do Filho], Nota.Nota_Filho
as [Nota do Filho] FROM Pai LEFT JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai LEFT JOIN Nota ON
Filho.Cod_Filho = Nota.Cod_Filho

6 3 5,00
7 3 10,00
8 4 9.5
9 4 9.0
10 5 10.0
11 5 7.8
12 6 9.0
13 7 7.5
14 7 6.7
15 8 8.8
16 8 9.0
17 9 10.0


68


O comando acima mostra todos os dados relacionados, pai com filho e filho com nota,
mostra tambm os pais com filhos e filhos sem nota e os pais que ainda esto sem filhos
cadastrados.




EVITANDO AMBIGUIDADE



Ambigidade um tipo de erro que acontece quando voc executa um Join de duas ou mais
tabelas que exibe colunas que tenham o mesmo nome nas duas ou mais tabelas envolvidas no
comando. Por exemplo, no join escrito logo abaixo, que associa a tabela pai e a tabela filho,
aparece a coluna Cod_Pai, que existe tanto na tabela Pai quanto na tabela Filho. Neste caso, o SQL
Server no consegui definir de qual das duas tabelas ele deve obter os dados da coluna Cod_Pai e
exibe o erro apresentado aps a exibio do comando:


SELECT Cod_Pai, Cod_Filho, Nome_Pai, Nome_Filho FROM Pai INNER JOIN Filho ON
Pai.Cod_Pai = Filho.Cod_Pai


Server: Msg 209, Level 16, State 1, Line 1 Ambiguous column name 'Cod_Pai'.


Para evitar a ambigidade, basta que voc defina para o SQL Server de qual das duas
tabelas ele dever obter os dados:


SELECT Pai.Cod_Pai, Cod_Filho, Nome_Pai, Nome_Filho FROM Pai INNER JOIN Filho ON
Pai.Cod_Pai = Filho.Cod_Pai


Desta forma no ocorrer mais o erro de nmero 209.
Como voc deve ter percebido, necessrio indicar a tabela de onde o SQL Server deve
obter os dados, apenas quando nas tabelas envolvidas no Join existirem colunas com nomes em
comum e quando voc precisar exibir justamente o contedo destas colunas.
Caso contrrio no ser necessrio especificar de qual tabela os dados devero ser obtidos.
Se voc sempre especificar o nome da tabela antes do nome da coluna em todos os joins que
escrever nunca cometer um erro de ambigidade.



SELECT Pai.Cod_Pai, Filho.Cod_Filho, Pai.Nome_Pai, Filho.Nome_Filho FROM Pai INNER JOIN
Filho ON Pai.Cod_Pai = Filho.Cod_Pai


69




UPDATE COM JOIN



Muitas vezes ser necessrio alterar os dados de uma tabela com base na existncia ou no
de dados relacionados em outra tabela. Por exemplo, voc poderia desejar aumentar a Idade para
mais um ano de todos os pais que possuem filhos. Para realizar esta tarefa, voc dever escrever
um Update com um Join:


UPDATE Pai SET Idade_Pai = Idade_Pai + 1 FROM Pai INNER JOIN Filho ON Pai.Cod_Pai =
Filho.Cod_Pai


Se voc tiver dificuldade em escrever este comando, escreva primeiro o update que deixa
todos os pais um anos mais velhos, depois escreva um comando select fazendo um join entre a
tabela pai e filho:


UPDATE Pai SET Idade_Pai = Idade_Pai + 1 SELECT * FROM Pai INNER JOIN Filho ON
Pai.Cod_Pai = Filho.Cod_Pai



Em seguida, retire a linha Select * do comando escrito acima e junte o Update inteiro com a
clausula From que restou do segundo comando:


UPDATE Pai SET Idade_Pai = Idade_Pai + 1 FROM Pai INNER JOIN Filho ON Pai.Cod_Pai =
Filho.Cod_Pai


Pronto, aqui est o Update com Join, que deixa um ano mais velhos apenas os pais que j
tem pelo menos um filho correspondente na tabela Filho.
Voc poder tambm escrever Updates com Joins que associam mais de duas
tabelas, conforma seja necessrio.




DELETE COM JOIN





70

Suponha que voc precisasse excluir os filhos que no receberam um respectivo pai na
tabela Pai. Para tanto, siga o mesmo raciocnio anterior. Escreva o comando delete, escreva o
select com o join, e depois retire a linha select do join, junte o update com a clusula from e apague
os filhos rfos.


DELETE Filho SELECT * FROM Pai RIGHT JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai WHERE
Pai.Cod_Pai IS NULL




Execute este comando aps retirar a linha do Select:



DELETE Filho FROM Pai RIGHT JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai WHERE Pai.Cod_Pai
IS NULL




JOINS ENTRE TABELAS QUE POSSUEM CHAVES COMPOSTAS



Suponha que voc tenha duas tabelas como as que seguem, onde a primeira tem uma chave
primaria composta de duas colunas e a segunda, que se relaciona com a primeira, tem uma chave
estrangeira composta das mesmas colunas:


CREATE TABLE Tab_A
(
ColunaA1 datatype Not Null,
ColunaA2 datatype Not Null,
ColunaA3 datatype Not Null,

Constraint PK_TabA Primary Key(ColunaA1,.ColunaA2)
)



CREATE TABLE Tab_B
(
ColunaB1 datatype Not Null Primary Key,
ColunaA1 datatype Not Null,
ColunaA2 datatype Not Null,


71

Constraint FK_TabB
Foreign Key(ColunaA1,ColunaA2) References Tab_A (ColunaA1,ColunaA2)
)



Para obter dados relacionados entre estas duas tabelas o joins dever ser escrito desta forma:




SELECT Tab_A.ColunaA1,
Tab_A.ColunaA2,
Tab_A.ColunaA3,
Tab_B.ColunaB1
FROM Tab_A INNER JOIN Tab_B
ON Tab_A.ColunaA1 = Tab_B.ColunaA1
AND Tab_A.ColunaA2 = Tab_B.ColunaA2
SUBQUERY


Neste assunto sero utilizadas as tabelas Pai e Filho (expostas logo abaixo) nas explicaes e
demonstraes.


CREATE TABLE Pai
(

Cod_Pai int identity not null Primary Key,

Nome_Pai char(30) not null,

Idade_Pai tinyint not null

)

CREATE TABLE Filho
(

Cod_Filho int identity not null Primary Key,

Cod_Pai int not null References Pai(Cod_Pai),

Nome_Filho char(30) not null,

Sexo_Filho char(01) not null Check(Sexo_Filho IN (F,M))



72

)


PAI
Cod_Pai Nome_Pai Idade_Pai
1 Daniel de Souza Leo Sobrinho 69
2 Agnaldo Diogo dos Santos 43
3 Fernando de Oliveira Leo 42
4 Jairo de oliveira Leo 39


FILHO
Cod_Filho Cod_Pai Nome_Filho Sexo_Filho
1 1 Renata de Oliveira Leo F
2 1 Fernando de Oliveira Leo M
3 1 Roberta de Oliveira Leo F
3 1 Jairo de Oliveira Leo M
4 2 Bruno Ferraira dos Santos M
5 2 Antonio dos Santos Neto M
6 2 Pedro Ferreira dos Santos M
7 3 Lucas Ribeiro Leo M
8 3 Helder Ribeiro Leo M
9 3 Mateus Ribeiro Leo M


As subqueries permitem que voc obtenha dados de uma tabela com base na existncia
destes dados em outra ou outras tabelas. Por exemplo, suponha que voc precisasse obter da
tabela Pai todos os dados do pai mais velho. Para tanto voc vai precisar utilizar a funo de
totalizao MAX() e uma subquery:


73



SELECT * FROM Pai WHERE Idade_Pai = (SELECT Max(Idade_Pai) FROM Pai)


O segundo select do comando acima chamado de subquery e o primeiro select chamado
de outer query ou apenas de query.
O SQL Server resolve a subquery obtendo o valor maior da coluna Idade_Pai e em seguida
obtem todas as colunas da tabela Pai onde a coluna Idade_Pai igual a esse valor obtido pela
subquery.
A resposta obtida :



PAI
Cod_Pai Nome_Pai Idade_Pai
1 Daniel de Souza Leo Sobrinho 69


O comando acima poderia ser lido da seguinte maneira: Selecione todos as colunas da
tabela Pai onde a idade do pai IGUAL { maior idade obtida com a subquery.
A mesma resposta poderia ser obtida se voc introduzisse a subquery com o operador IN:


SELECT * FROM Pai WHERE Idade_Pai IN (SELECT Max(Idade_Pai) FROM Pai)



O comando acima poderia ser lido da seguinte maneira: Selecione todos as colunas da
tabela Pai onde a idade do pai EST no conjunto de dados retornado pela subquery.
Para obter este tipo de informao, ou seja, dados que sejam do maior ou do menor valor, s
possvel quando se utiliza uma subquery.




SUBQUERY INTRODUZIDA COM OPERADOR DE COMPARAO


As subqueries introduzidas com os operadores de comparao devem retornar sempre
apenas um nico valor. Por exemplo, a subquery que obtm o maior valor da coluna
Idade_Pai, retorna apenas um valor o maior.
Voc poderia utilizar outros sinais de comparao, como por exemplo:


a) Obtenha todos os dados dos pais sem mostrar o Pai mais velho:



74


SELECT * FROM Pai WHERE Idade_Pai <> (SELECT Max(Idade_Pai) FROM Pai)




SELECT * FROM Pai WHERE Idade_Pai < (SELECT Max(Idade_Pai) FROM Pai)



b) Obtenha todos os dados do pai mais novo:



SELECT * FROM Pai WHERE Idade_Pai = (SELECT Min(Idade_Pai) FROM Pai)


SUBQUERY INTRODUZIDA COM IN OU NOT IN



As subqueries introduzidas com os operadores IN ou NOT IN devem retornar sempre valores
de apenas uma coluna, mas podero retornar mais de uma linha como resposta.
Por exemplo, suponha que voc precisasse obter da tabela Pai todas as colunas apenas dos
pais que possuem um ou mais filhos registrados na tabela Filho. Para tanto voc poderia escrever os
seguintes comandos:



SELECT * FROM Pai WHERE Cod_Pai IN (SELECT Cod_Pai FROM Filho)



Suponha que voc precisasse obter da tabela Pai todas as colunas apenas dos pais que ainda
NO possuem filhos registrados na tabela Filho. Para tanto voc poderia escrever os seguintes
comandos:



SELECT * FROM Pai WHERE Cod_Pai NOT IN (SELECT Cod_Pai FROM Filho


O resultado obtido com o uso das subqueries podem ser obtidos pelos joins, pois os joins
apresentam melhor performance do que as subqueries:




SELECT * FROM Pai WHERE Cod_Pai IN (SELECT Cod_Pai FROM Filho)

Substitua o comando escrito acima por:


75



SELECT DISTINCT Pai.* FROM Pai INNER JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai



SELECT * FROM Pai WHERE Cod_Pai NOT IN (SELECT Cod_Pai FROM Filho)

Substitua o comando escrito acima por:

SELECT Pai.* FROM Pai LEFT JOIN Filho ON Pai.Cod_Pai = Filho.Cod_Pai WHERE
Filho.Cod_Pai IS NULL


Subquery Introduzida com EXISTS e NOT EXISTS




Voc poder utilizar os operadores EXISTS e NOT EXISTS para obter, por exemplo dados
relacionados entre as tabelas pai e Filho. Para obter todos os pais que possui pelo menos um
filho registrado na tabela Filho voc poderia escrever o seguinte comando:



SELECT * FROM Pai WHERE EXISTS (SELECT Cod_Pai FROM Filho WHERE Filho.Cod_Pai =
Pai.Cod_Pai)



Para obter os dados da tabela Pai, mas apenas dos pais que no possuem um
filho correspondente na tabela Filho, voc poderia escrever o seguinte comando:



SELECT * FROM Pai WHERE NOT EXISTS (SELECT Cod_Pai FROM Filho WHERE Filho.Cod_Pai
= Pai.Cod_Pai)



Observe que nas subqueries acima, utiliza-se na clusula Where a tabela Pai, que no foi
citada na clusula From destas mesmas subqueries. A tabela Pai da clusula Where das subqueries
est se relacionando com a Query. Portanto, para cada linha selecionada da tabela Pai pela
query, o SQL Server tem que executar uma vez a subquery que obtm dados da tabela Filho.
Assim, se houver na tabela Pai, 10 Pais registrados, o SQL Server executar 10 vezes a subquery
correspondente.
Justamente porque estas subqueries esto amarradas com a query, elas so chamadas de
Subqueries Correlacionadas.
As Subqueries Correlacionadas normalmente consomem muitos recursos do sistema para


76

serem processadas, portanto sempre d preferncia para obter seus dados escrevendo joins
que tm um melhor processamento.
interessante que voc conhea as subqueries para poder interpret-las quando
necessrio.
Voc poder se deparar com subqueries que formam uma coluna resposta de um select. Por
exemplo, a subquery abaixo apresenta todos os dados da tabela Pai e apresenta tambm uma
coluna a mais (que no existe fisicamente na tabela Pai) que mostra a quantidade de filhos que
cada pai possui. Observe:

SELECT *,

(SELECT Count(Cod_Pai) FROM Filho

WHERE Filho.Cod_Pai = Pai.Cod_Pai) AS Qtd_Filho

FROM Pai


Note que a subquery acima se correlaciona com a query atravs da tabela Pai.



SUBSTITUINDO SUBQUERIES



1 Para selecionar todos os pais que possuem filhos existem trs possibilidades. A ltima
apresentar melhor performance.




/* Subquey correlacionada*/

SELECT * FROM Pai

WHERE EXISTS (SELECT Cod_Pai FROM Filho

WHERE Filho.Cod_Pai = Pai.Cod_Pai)



/* Subquery no correlacionada*/

SELECT * FROM Pai

WHERE Cod_Pai IN (SELECT Cod_Pai FROM Filho)



77



/* Inner Join*/

SELECT DISTINCT Pai.*

FROM Pai INNER JOIN Filho

ON Pai.Cod_Pai = Filho.Cod_Pai


2 Para selecionar todos os pais que no possuem filhos existem trs possibilidades. A lttima
apresentar melhor performance.


/* Subquey correlacionada*/

SELECT * FROM Pai

WHERE NOT EXISTS (SELECT Cod_Pai FROM Filho

WHERE Filho.Cod_Pai = Pai.Cod_Pai)


/* Subquery no correlacionada*/

SELECT * FROM Pai

WHERE Cod_Pai NOT IN (SELECT Cod_Pai FROM Filho)


/* Left Join e IS NULL*/

SELECT Pai.*

FROM Pai LEFT JOIN Filho

ON Pai.Cod_Pai = Filho.Cod_Pai

WHERE Filho.Cod_Pai IS NULL




3 Para apresentar todos os dados da tabela Pai e a quantidade de filhos que cada pai possui
existem duas possibilidade, a ltima oferece melhor performance:




78


/*Subquery Correlacionada*/

SELECT *,

(SELECT Count(Cod_Pai) FROM Filho

WHERE Filho.Cod_Pai = Pai.Cod_Pai) AS Qtd_Filho

FROM Pai



/* Left Join com Group By e a funo de totalizao Count() */

SELECT Pai.Cod_Pai,Pai.Nome_Pai,Count(Filho.Cod_Pai) AS Qtd_Pai

FROM Pai LEFT JOIN Filho

ON Pai.Cod_Pai = Filho.Cod_Pai

GROUP BY Pai.Cod_Pai,Pai.Nome_Pai




OBS: O ganho de performance s perceptvel quando as tabelas possuem uma quantidade
razovel de dados.


SUBQUERIES ANINHADAS


As subqueries aninhadas so formadas de vrios comandos SELECT. Voc ter uma query e
duas ou mais subqueries. Observe abaixo as tabelas utilizadas como exemplo:


PRODUTO
Cod_Prod Nome_Prod Qtd_Prod Val_Prod
1 Caderno 100 15.56
2 Lpis 200 1.52
3 Borracha 500 0.58
CLIENTE


79

































Para obter, por exemplo, os dados de todos os cliente solteiros que j fizeram pelo menos
um pedido, voc poderia escrever o seguinte somando:


SELECT * FROM Cliente WHERE Cod_Cli NOT IN(SELECT Cod_Cli FROM Conjuge) AND
Cod_Cli IN(SELECT Cod_Cli FROM Pedido)



Segue abaixo a resposta obtida:


CLIENTE
Cod_Cli Nome_Cli Renda_Cli
3 Jairo Gato 3500,00
Para obter os dados de todos os clientes que compraram, por exemplo o produto 1, escreva
Cod_Cli Nome_Cli Renda_Cli
1 Joo Gaucho 5000,00
2 Daniel Leo 6000,00
3 Jairo Gato 3500,00
4 Roberta Zapata 5500,00
5 Helena Leito 2500,00
CNJUGE
Cod_Cli Nome_Conj Renda_Conj Idade_Conj
1 Maria Souza Gaucho 2500,00 20
2 Helena Leo 3030,00 25
PEDIDO
Num_Ped Cod_Cli Data_Ped Val_Ped
1 1 01/05/02 2800,00
2 3 02/06/02 3055.20
ITENS
Num_Ped Cod_Pro
d
Qtd_Prod
1 1 50
1 2 10
2 1 30
2 2 10
2 3 5


80

o seguinte comando:


SELECT * FROM Cliente
WHERE Cod_Cli IN (SELECT Cod_Cli FROM Pedido
WHERE Num_Ped IN (SELECT Num_Ped FROM Itens
WHERE Cod_Prod = 1))



UPDATE COM SUBQUERY



Voc poder alterar dados de uma tabela com base na existncia de dados em outras tabelas
utilizando subqueries. Por exemplo, voc poderia alterar a renda dos clientes que compraram o
produto de cdigo 1. Observe:



UPDATE Cliente
SET Renda_Cli = Renda_Cli * 1.1
WHERE Cod_Cli IN (SELECT Cod_Cli FROM Pedido
WHERE Num_Ped IN (SELECT Num_Ped FROM Itens
WHERE Cod_Prod = 1))




DELETE COM SUBQUERY



Voc poder excluir dados de uma tabela com base na existncia de dados em outras
tabelas utilizando subqueries. Por exemplo, voc poderia excluir da tabela produto todos os produtos
que nunca foram vendidos:



DELETE Produto
WHERE Cod_Prod NOT IN (SELECT Cod_Prod FROM Itens)

Você também pode gostar