Escolar Documentos
Profissional Documentos
Cultura Documentos
Transact-SQL - 50 Minutos PDF
Transact-SQL - 50 Minutos PDF
TRANSACT - SQL
O que é Datatype.................................................................................................................................... 11
Critério ............................................................................................................................................ 58
Resumo ............................................................................................................................................ 58
IN / NOT IN ....................................................................................................................................... 58
Argumentos ....................................................................................................................................... 63
TOP n ................................................................................................................................................. 65
Group By ................................................................................................................................................ 73
HAVING.............................................................................................................................................. 78
ROLLUP()............................................................................................................................................ 78
CUBE() ............................................................................................................................................... 79
CASE ....................................................................................................................................................... 80
UNION ............................................................................................................................................... 89
GROUPING SETS()............................................................................................................................... 93
SUBQUERY............................................................................................................................................ 124
INTRODUÇÃO
A liguaguagem SQL surge com a criação do Modelo Relacional proposta pelo Dr. Edgard
Frank Codd já nos anos 70.
SQL é o nome que foi atribuído á 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 laboratórios da IBM – USA.
Quando criada recebeu outro nome, SEQUEL, que significava “Structured English Query
Language” – Linguagem Estruturada em Inglês para Pesquisa”.
Com o passar do tempo a liguagem teve seu nome alterado para SQL, mas lá nos Estados
Unidos seu nome ainda é pronunciado como “Sequel”.
Também com o passar do tempo, com sua aceitação e utilização pelos profissionais de banco
banco de dados, a liguagem SQL acabou se tornando um padrão. Na realidade, surgiram
vários dialétos desta liguagem e houve a necessidade de padronizar a sua utilização.
Sendo assim, em 1986 ela foi padronizada pelo instituto ANSI e em 1987 pelo ISO.
A padronização da SQL foi revista em 1992 e, justamente por isso passa a ser chamada de
SQL-92 ou SQL2
Em 1999 houve outra revisão onde a linguagem passa a se chamar SQL:1999 ou SQL3.
SQL é o nome que foi atribuído á linguagem declarativa utilizada no tratamento de dados
armazenados no formato relacional.
GRANT
REVOKE
CREATE
ALTER
DROP
SELECT
INSERT
UPDATE
DELETE
Apesar da padronização, ainda há uma certa diferença 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 começar pelas demonstrações dos comandos da
DML.
O QUE É UM DATABASE
Todo database do SQL Server tem pelo menos dois arquivos, uma para armazenar dados de
tabelas e de indices e o outro para armazenar as transações (comandos que inserem,
alteram e excluem os dados de uma tabela).
Esses databases poderão, se necessário, ter mais de um arquivo de dados e/ou mais de um
arquivo de transações.
Como o objetivo deste tutorial é exibir a forma de utilização dos comandos DML, vamos aqui
criar um database com todas as opções definidas como default e com os arquivos de dados e
de transações que o próprio SQL Server define durante a execução do comando CREATE
DATABASE.
Clique no menu Start / Programs / Microsoft SQL Server 2008/ SQL Server
Management Studio.
Surge para você uma área onde os comandos são digitados e executados.
USE [50minutos]
Observe no alto e do lado esquerdo da sua tela, que aparece o nome 50minutos
como o database corrente.
Uma Tabela é um objeto bidimensional, composta por Colunas e Linhas, onde os dados são
armazenados dentro de um database.
O exemplo abaixo exibe uma Tabela chamada Cliente, formada pelas Colunas Cod_Cli –
que representa um código 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 código é o número
1 e o nome é Agnaldo e o cliente de número 2 cujo nome é Renata:
1 Agnaldo 30000.00
2 Renata 5000.00
O QUE É DATATYPE
Data type, ou tipo de dado, é o formado no qual os dados de cada coluna de uma tabela são
armazenados em disco.
O Microsoft SQL Server oferece vários datatypes que chamamos de built-in, ou seja,
construídos internamente. Eles são divididos em categorias como, por exemplo, categoria
dos datatypes numéricos, 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, números
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 dígitos.
E para a coluna Renda_Cli vamos utilizar o datatype decimal(10,2), que aceitará dados
numéricos com duas casas decimais.
Para que você possa criar esta tabela, inserir suas duas linhas de dados e exibir seu
conteúdo, siga as instruções abaixo.
Na mesma tela e logo após você ter executado o comando USE [50minutos] para acessar
este database, escreva os seguintes comandos:
Cod_Cli int ,
Nome_Cli varchar(100) ,
Renda_Cli decimal(10,2) ,
Para inserir os dados dos dois clientes em questão vamos utilizar o comando
INSERT (que será visto em mais detalhes em outros tópicos deste tutorial).
Então, escreva os comandos:
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
apostofo, 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á começando 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 fácil detectá-lo e corrigí-lo.
d - Por causa do Collation padrão da instalação do software, o SQL Server não fará
diferença 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 padão da instalação da iInstância, da
criação do database e da definição da coluna que utilizamos em Nome_Cli, para
encontrar os dados ele não fará diferenciação entre letras maiúsculas e minúsculas.
/*
Comentarios feitos
em múltiplas Linhas
*/
Nosso próximo passo será a exibição dos dados que acabaram de ser inseridos.
Para tanto, na mesma tela, escreva o comando abaixo:
Pronto! Agora você já tem um database, uma tabela com três colunas, e duas linhas de dados
inseridas!
Se você chegou até aqui, parabéns pelos primeiros passos na sintaxe SQL da Microsoft.
Como foi visto anteriormente, DML é um grupo de comandos da linguagem SQL que
significa Data Manipulation Language – Linguagem de Manipulação de Dados. Dela fazem
parte os comandos SELECT, INSERT, UPDATE e DELETE.
Como você já deve ter percebido, SELECT é o comando da liguagem SQL que utilizamos para
selecionar/exibir os dados de uma tabela.
A sintaxe da SQL nos permite exibir dados de várias maneiras atavés das váriações do
comando SELECT.
Para que você possa conhecer estas possibilidades de sintaxe vamos criar, no database
50minutos, uma outra tabela chamada Funcionario, vamos inserir nela cinco linhas de
dados e assim trabalhar com este objeto.
-----------------------------------------------------------------------
Use 50minutos
-----------------------------------------------------------------------
Cod_Func int ,
Nome_Func varchar(100) ,
Sexo_Func char(1) ,
Sal_Func Decimal(10,2) ,
Data_Func Datetime ,
----------------------------------------------------------------------
Para exibir os dados de todas as colunas de uma determinada tabela você pode utilizar uma
das duas sintaxes exibidas abaixo.
2 – Exibindo os dados de todas as colunas de uma tabela especificando o nome de uma por
uma:
SELECT Cod_Func,
Nome_Func,
Sexo_Func,
Sal_Func,
Data_Func
FROM Funcionario
Você já deve ter percebido que para exibir os dados de todas as colunas da tabela em outra
ordem que não seja a da definição de sua estrutura, basta escrever o nome das colounas na
sequência em que desejar exibí-las.
SELECT Sexo_Func,
Data_Func,
Cod_Func,
Nome_Func,
Sal_Func
FROM Funcionario
Agora ficou fácil, para exibir os dados de alguns colunas de uma tabela, basta escrever
apenas seus nomes no comando SELECT e executá-lo.
Exemplo_01
-- na sequência desejada
SELECT Cod_Func,
Nome_Func,
Data_Func
FROM Funcionario
Exemplo_02
-- na sequência desejada
SELECT Data_Func,
Cod_Func,
Nome_Func
FROM Funcionario
5 – Exibindo dados de uma tabela utilizando Alias no nome das colunas – Demonstração das
sintaxes disponíveis no Microsoft SQL Server
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
próprio nome atribuído á cada uma das colunas, que no nosso caso é: Cod_Func,
Nome_Func, Sexo_Func, Sal_Func e Data_Func.
Só que isso pode não ficar claro para o usuário que vai utilizar, por exemplo, um relatório se
você deixar que estes nomes se apresentem para ele como estão na definição da estrutura
da tabela.
Nós sabemos, por exemplo, o que armazena a coluna Sal_Func, mas para um usuário pode
ser que não esteja claro que ela representa o salário de cada funcionário inserido neste
objeto.
Assim sendo, para que possamos gerar relatórios mais claros para nossos usuários podemos
atribuir apelidos para os nomes de cada uma das colunas. Estes apelidos são chamados de
Alias e a Microsoft nos permite escrever os alias de várias maneiras.
-- Primeira sintaxe:
Nome_Func AS Nome,
Sexo_Func AS Sexo,
Sal_Func AS Salário,
Data_Func AS Data
FROM Funcionario
--Segunda Sintaxe:
Nome_Func Nome,
Sexo_Func Sexo,
Sal_Func Salário,
Data_Func Data
FROM Funcionario
-- Terceira Sintaxe:
Nome = Nome_Func ,
Sexo = Sexo_Func ,
Salário = Sal_Func ,
Data = Data_Func
FROM Funcionario
-- Quarta sintaxe:
FROM Funcionario
-- Quinta Sintaxe:
FROM Funcionario
-- Sexta Sintaxe:
FROM Funcionario
--Sétima Sintaxe:
FROM Funcionario
--Oitava Sintaxe:
FROM Funcionario
--Nona Sintaxe:
FROM Funcionario
-- Décima Sintaxe:
FROM Funcionario
FROM Funcionario
FROM Funcionario
Obs.: É claro que, apenas na execução de um único SELECT, podemos utilizar as sintaxes
exibidas acima misturadas umas com as outras, mas lógicamente é muito melhor, muito
mais elegante que se tenha um padrão para a sua utilização.
Você poderia acrescentar esta nova coluna na tabela executando, para tanto, o comando
ALTER TABLE. Mas aqui não é o caso. Suponha que você deseja apenas exibir a
nacinalidade brasileira para todos os funcionários apenas uma úniva vez.
FROM Funcionario
Nome_Func AS Nome,
Sexo_Func AS Sexo,
Sal_Func AS Salário,
Data_Func AS Data,
'Brasileira' AS Nacionalidade
FROM Funcionario
Nome_Func AS Nome,
Sexo_Func AS Sexo,
'Brasileira' AS Nacionalidade
FROM Funcionario
Obs.: Com relação ao apelido das colunas, obviamente você poderá utilizar, das sintaxes
apresentadas anteriormente, aquela que desejar. Para efeito de demonstração neste tutorial
estamos utilizando a primeira das sintaxes exibidas no ítem 3.5.
Agora vamos supor que você precise exibir quanto seria o novo salário de cada funcionário
se lhes fosse aplicado um aumento de 10% e um aumento salarial de 20%. Só que, na
realidade, você não deseja realmente aplicar o aumento promovendo uma alteração nos
dados, você deseja apenas visualizar os novos valores.
Nome_Func AS Nome,
'Brasileira' AS Nacionalidade
FROM Funcionario
Observe também que é possível exibir colunas virtuais como é o caso da nacionalidade e
como é o caso dos aumentos salariais num mesmo SELECT.
Nome_Func AS Nome,
'Brasileira' AS Nacionalidade
FROM Funcionario
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 cláusula 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.
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
várias vezes na mesma coluna.
A query abaixo exibirá apenas uma vez cada valor inserido. Sendo assim considerando, por
exemplo, que o salário de 2500,00 tenha sido inserido duas vezes na tabela, o comando
abaixo apresentará este valor apenas uma vez.
A query abaixo exibirá apenas uma vez os dados repetidos considerando os valores das
duas colunas a seram exibidas.
Como você já deve ter percebido, INSERT é o comando da liguagem SQL que utilizamos
para incluir os dados de uma tabela.
Para que você possa conhecer estas possibilidades de sintaxe da utilização deste comando
vamos acessar o database [50minutos], e fazer algumas demonstrações, 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 execução.
Quando trabalhamos com a linguagem SQL do Microsoft SQL Server, nos acostumamos a
inserir dados em uma tabela escrevendo apenas a seguinte cláusula:
INSERT <NomeTabela>
Acontece que, o comando da linguagem SQL ANSI pra inclusão de dados em uma
determinada tabela é na verdade INSERT INTO.
Então você já deve ter percebido que a sintaxe SQL da Microsoft nos permite omitir a
cláusula INTO na execução de inclusões de dados nas tabelas de um sistema.
Execute os códigos abaixo e perceba que os dois vão funcionar perfeitamente e inserem os
mesmos dados, do mesmo jeito na tabela Funcionario:
GO
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 criação da mesma.
Neste caso não há a necessidade de escrever o nome de cada coluna onde estamos inserindo
os valores, pois presume-se que estamos passando-os na sequência de sua criação.
Já no INSERT Declarativo, como o próprio nome já indica, nós declaramos a ordem das
colunas na qual passaremos os valores durante uma inclusão de dados.
Esta forma de escrita do comando INSERT é interessante porque nos permite inserir os
dados para as colunas passando os valores na sequência em que desejarmos, sem a
necessidade de obedecer a order utilizada na criação da tabela.
Observe:
VALUES('M',GETDATE(),1,1000.00,'Marcos')
(Sexo_Func,Data_Func,Cod_Func,Sal_Func, Nome_Func)
VALUES('M',GETDATE(),1,1000.00,'Marcos')
Observe o código abaixo, onde estamos omitindo a inclusão de dados para a coluna
Data_Func.
VALUES(1,1000.00,'Marcos')
A partir da versão 2008 do Microsoft SQL Server podemos utilizar a sintaxe abaixo, onde
escrevemos apenas uma vez o comando completo e na sequência passamos apenas uma
lista de valores que desejamos inserir de uma só vez.
(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())
A composição do comando SELECT com o comando INSERT é utilizada para copiar dados
de uma tabela para outra.
Suponha que você tenha criado a tabela Empregado, cuja estrutura segue no código abaixo,
e que precise copiar para ela os dados da tabela Funcionario.
Cod_Emp int ,
Nome_Emp varchar(100) ,
Sexo_Emp char(1) ,
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 cópia desejada:
INSERT Empregado
Caso_02 – Estruturas diferentes, com a tabela que recebe os dados tendo menos
colunas que a tabela origem.
Suponha agora qua a tabela para a qual você deseja copiar dados seja essa cujo código segue
abaixo.
Cod_Aux int ,
Nome_Aux varchar(100) ,
Sexo_Aux char(1) ,
Note que neste caso temos que utilizar o comando SELECT, obtendo da tabela Funcionário
apenas os dados que correspondem às colunas da tabela Auxiliar.
INSERT Auxiliar
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 Estagiário)
para a qual não há valor na tabela origem.
Cod_Estag int ,
Nome_Estag varchar(100) ,
Sexo_Estag char(1) ,
Sal_Estag Decimal(10,2) ,
Data_Estag Datetime ,
Nac_Estag varchar(100) ,
Então para copiar dados de Funcionario para Estagiário teremos que utilizar um dos
comandos abaixo:
INSERT Estagiario
INSERT Estagiario
INSERT Estagiario
INSERT Estagiario
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 Estagiário, já haja um valor Default definido para a coluna
Nac_Estag e que você deseje inserir um valor nulo para a Data_Estag.
-- Inserindo dados na tabela Estagiario, deixando que o próprio SQL -- Server insira
valores nas colunas Nac_Estag e Data_Estag
Obs.: Quando inserimos um Null em uma coluna estamos determinando que o SQL Server a
deixe sem valor algum. Portanto Null quer dizer ausência de valor!
UPDATE é o comando que utilizamos para modificar os dados em uma ou mais colunas.
1 – A cláusula SET
Em todo e qualquer comando UPDATE você deverá escrever UMA cláusula SET, para se
referenciar a(s) coluna(s) que deseja alterar.
Por exemplo: no script abaixo, estamos criandos uma tabela chamada Pessoa no database
[50minutos]. Estamos também inserindo cinco registro nesta tabela.
-----------------------------------------------------------------------
Use [50Minutos]
-----------------------------------------------------------------------
Cod_Pes int ,
Nome_Pes varchar(100) ,
Sexo_Pes char(1) ,
Sal_Pes Decimal(10,2) ,
Data_Pes Datetime ,
----------------------------------------------------------------------
----------------------------------------------------------------------
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
Suponha agora que você precise modificar os dados da tabela pessoa da seguinte maneira:
O comando UPDATE para este caso tem que ser escrito assim:
UPDATE Pessoa
Sexo_Pes = 'x',
2 – A cláusula FROM
Para o comando UPDATE a cláusula FROM é opcional. Portanto você poderia escrever os
UPDATEs anteriores assim, se quisesse:
-----------------------------------------------------------------------
UPDATE Pessoa
FROM Pessoa
-----------------------------------------------------------------------
UPDATE Pessoa
Sexo_Pes = 'x',
FROM Pessoa
-----------------------------------------------------------------------
É possível excluir valores de apenas uma coluna? Se esta for também a sua dúvida, é só
pensar que o comando DELETE excluir linhas da tabela. Não 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)!
DELETE Pessoa
Obs:
A CLÁUSULA WHERE
A cláusula 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 utiilizar operadores para fazer a seleção dos mesmos.
É através dos operadores que podemos dizer para o SQL Server qual dados deve ser
afetado pelos comandos DML.
Para que possamos fazer demonstrações da utilização da cláusula WHERE vamos executar o
script abaixo, que cria uma tabela chamada Produto, no database [50minutos] e insere 10
registros de dados.
-----------------------------------------------------------------------
Use [50minutos]
-----------------------------------------------------------------------
Cod_Prod int,
Nome_Prod char(50),
Tipo_Prod char(20),
Qtd_Prod int,
Val_Prod decimal(10,2)
Igual (=)
Maior (>)
Menor (<)
a) Suponha que você deseje obter os dados da tabela Produto, mas apenas do Produto cujo
código é igual a 1. Para tento você teria que escrever o comando abaixo:
WHERE Cod_Prod = 1
b) Se desejasse exibir apenas os dados dos Produtos do tipo Cozinha, teria que escrever o
commando a seguir:
Operadores Lógicos
E (AND)
Ou (OR)
Negação (NOT)
Obviamente é possivel escrever mais de uma condição para a cláusula WHERE, como no
exemplo abaixo, onde desejamos obter todos os dados do Produto do tipo `Cozinha’, mas
que tenham também o valor maior do que 500.00.
Poderíamos também querer exibir todos os valores dos Produto to tipo Cozinha OU dos
Produtos com valor acima de 500.00.
E assim, segue. Se você precisar, poderá colocar quantas condições precisar na cláusula
WHERE, sendo que se houver mais de uma, elas deverão ser escritas utilizando os
operadores lógicos AND e/ou OR.
Se você precisasse de todos os produtos que não forem do tipo ‘Cozinha’ poder| escrever o
código abaixo:
Eu poderia escrever a query abaixo para obter todos os produtos que o valor não seja maior
do que 500.00:
Suponha que você queira exibir os dados dos Produtos cujos códigos sejam 2, 4 e 6. Você
deseja obter da tabela os três produtos. Para conseguir isso terá que escrever o código
abaixo:
WHERE Cod_Prod = 2
OR Cod_Prod = 4
OR Cod_Prod = 6
Mas com se utilizar o critério de pesquisa IN poderá substituir o codigo anterior pelo que
segue e conseguirá os mesmos dados.
Imagine agora que seja necessário que você obtenha da tabela todos os Produtos menos os
de código 2, 4 e 6. Pata tanto terá que escrever o código abaixo:
O comando abaixo nos dará todos os produtos cujo valor estejam na faixa de 500.00 e
2000.00 (inclusive os produtos que custarem 500.00 e 2000.00).
O comando abaixo nos dará todos os produtos cujo valor estejam fora da faixa de 500.00 e
2000.00:
Escrevendo o SELECT abaixo obtemos todos os Produtos cujo nome seja exatamente
Geladeira:
Porém se desejarmos obter todos os produtos que o nome comece, contenha ou termine
com uma determinada letra ou sílaba teremos que utilizar o crítério de pesquisa LIKE e
para obter os dados negando a existência dos mesmos critérios, teremos que utilizar NOT
LIKE. Observe exemplos abaixo:
-- Selecione os dados de todos os produtos onde o nome tenha até cinco letras.
Observe que cada letra é representada aqui por um traçinho
-- Selecione todos os Produtos, onde o nome Não comece com a letra “G”,
-- O exemplo a seguir exibe todos os Produtos cujo nome comece com -- qualquer
letra, contenha a sequência de letrar “ei” e contenha logo -- em seguida, qualquer
letra, diferente de ‘a’.
-- O exemplo abaixo exibe os dados de todos os produtos, cujo nome não -- é Nulo
-- Nulo
Critério Resumo
Obs.:
UPDATE Produto
DELETE Produto
A CLÁUSULA ORDER BY
A ordenação pode ser feita por uma ou mais coulnas, e estas podem estar armazenadas no
formato numérico, caracter, data e data/hora.
Para exemplificar as explicações sobre esta clausula, vamos criar a tabela Material no
database [50minutos], como mostra o script abaixo:
-----------------------------------------------------------------------
Use [50minutos]
-----------------------------------------------------------------------
Cod_Mat int,
Tipo_Mat char(1),
Nome_Mat char(50),
Qtd_Mat int,
Val_Mat decimal(10,2)
-----------------------------------------------------------------------
(1,'A','Caderno Espiral',100,12.50)
(2,'A','Lápis Preto',500,1.50)
(3,'A','Lápis 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','Régua de Madeira',3500,9.00)
(11,'C','Régua de Plástico',2586,10.00)
(12,'C','Folhas de Papel',2587,5.50)
-----------------------------------------------------------------------
Se você prestar atenção poderá observar que, na coluna Nome_Mat (que representa o nome
dos materiais inseridos na tabela), os dados foram inseridos sem obedecer a nenhuma
ordenação específica.
Suponha então que você precisasse gerar um relatório que exiba todos os dados da tabela
Material em ordem alfebética do nome.
Para cumprir com esta tarefa basta escrever e executar o código abaixo:
ORDER BY Nome_Mat
Podemos orderna os dados a serem exibidos pelo nome da coluna ou pela posição da
mesma em duas situações.
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 ordenação feita
anteriormente.
ORDER BY 3
O comando abaixo também exibe os dados ordenados pela coluna Nome_Mat, que neste
caso é a segunda coluna da select list.
ORDER BY 2
ARGUMENTOS
Podemos utilizar argumetos em cada uma das colunas que escrevermos na cláusula ORDER
BY.
ASC – Ascendente
ORDER BY 3 ASC
Portanto escrevendo ASC, ou não, os dados serão apresentados com a mesma ordenação
DESC – Decrescente
ORDER BY 3 DESC
COLLATE
A ordenação feita pelo COLLATE só se aplica às colunas que tenhas os datatypes char,
varchar, nchar e nvarchar.
A CLÁUSULA TOP
A cláusula TOP também poderá ser utilizada em pesquisas que contenham a cláusula
WHERE com todas as sintaxes exibidas nos ítens do tópico 4. O SQL Server obtem os dados
da tabela de acordo com os critérios da cláusula WHERE e exibe os n primeiros registros,
conforme especificado logo após a cláusula TOP.
TOP N
A letra n que acompanha a cláusula TOP é uma expressão numérica que representa a
quantidade de primeiros registros que se deseja obter em uma pesquisa. Observe os
exemplos que seguem:
TOP N PERCENT
As cláusulas TOP n PERCENT são utilizadas para que o SQL Server obtenha exiba os n por
cento (n%) dos dados retornados por uma deterimanda pesquisa
A cláusula WITH TIES pode ser utilizada com TOP n e com TOP n PERCENT, mas deverá
ser acompanhada pelas cláusulas ORDER BY.
Por exemplo, no comando abaixo, serão apresentados os cinco primeiros registros da tabela
material, porém outras linhas de dados poderão ser exibidas se houver outros registros cujo
valor do material(Val_Mat) seja igual ao valor do quinto material deste conjunto de valores.
ORDER BY Val_Mat
Estas cláusulas são úteis para se obter, por exemplo, o material mais caro ou mais barato
desta tabela. Observe os exemplos:
ORDER BY Val_Mat
Você também pode utilizar a cláusula TOP com os comandos UPDATE e DELETE para dizer
para o SQL Server alterar ou excluir os n primairos registros de uma tabela.
A CLÁUSULA OUTPUT
A cláusula OUTPUT serve para que você possa “obter os dados” antes, ou depois, deles
serem alterados ou excluídos de uma tabela.
Para exemplificar a cláusula vamos utilizar a tabela abaixo com os dados que seguem:
----------------------------------------------------------------------
Use [50minutos]
----------------------------------------------------------------------
Cod_Bonus int,
Cod_Cli int,
Data_Bonus smalldatetime,
Val_Bonus decimal(10,2)
----------------------------------------------------------------------
(1,2,Getdate(),50.00,)
(1,1,Getdate(),150.00,)
(1,3,Getdate(),80.00,)
----------------------------------------------------------------------
Cod_Premio int,
Cod_Cli int,
Data_Premio smalldatetime,
Val_Premio decimal(10,2)
----------------------------------------------------------------------
Observe que a tabela Bonus recebe dados e que a tabela Premio é criada, mas permanece
vazia.
UPDATE Bonus
OUTPUT DELETED.*
UPDATE Bonus
OUTPUT INSERTED.*
UPDATE Bonus
OUTPUT DELETED.Cod_Cli,DELETED.Val_Bonus
-- Val_Bonus
UPDATE Bonus
OUTPUT INSERTED.Cod_Cli,INSERTED.Val_Bonus
-- tabela
UPDATE Bonus
-- excluídos
----------------------------------------------------------------------
-- excluídos
----------------------------------------------------------------------
-- Exclui todos os dados da tabela, mas os salva em outra tabela antes -- de excluir.
DELETE Pessoa
GROUP BY
GROUP BY é uma cláusula que utilizamos para produzir totalizações com agrupamentos de
dados.
As totalizações são feitas através das built-on functions Sum(), Count(), Max(), Min(),
Avg(), entre outras e os agrupamentos são feitos com os argumentos HAVING, RULLUP(),
CUBE(), GROUPING SET().
-----------------------------------------------------------------------
USE [50minutos]
-----------------------------------------------------------------------
-----------------------------------------------------------------------
-----------------------------------------------------------------------
(2,'B',1,'Sofá',200,1500.00),
(3,'A',2,'Mesa',100,200.00),
(4,'A',2,'Armário',300,200.00),
(5,'C',1,'Cama',500, 1000.00),
(6,'B',1,'Poltrona',100,250.00),
(7,'B',2,'Sofá',200,300.00),
(8,'C',2,'Cama',100,150.00),
(9,'A',1,'Armário',200,800.00),
(10,'C',1,'Guarda-Roupa',100,1500.00)
-----------------------------------------------------------------------
FUNÇÕES DE TOTALIZAÇÃO
UTILIZANDO GROUP BY
SELECT Cod_Tipo,
Sum(Qtd_Prod) AS Qtd_Prod
FROM Produto
GROUP BY Cod_Tipo
Se quiséssemos exibir o total de produtos em estoque por tipo e por linha de produto
teríamos que executar o código abaixo:
SELECT Cod_Tipo,Cod_Linha,
Sum(Qtd_Prod) AS Qtd_Prod
FROM Produto
GROUP BY Cod_Tipo,Cod_Linha
HAVING
SELECT Cod_Tipo,
Sum(Qtd_Prod) AS Qtd_Prod
FROM Produto
GROUP BY Cod_Tipo
ROLLUP()
O exemplo abaixo exibe a quantidade de produto em estoque por tipo e por linha de
produto, dando sub-totais por tipo, sub-totaispor linha e um total geral.
SELECT Cod_Tipo,Cod_Linha,
Sum(Qtd_Prod) AS Qtd_Prod
FROM Produto
CUBE()
Cube vai fazer com que o SQL Server gere os dados inicialmente iguais ao Rollup, só que
vai exibir totalizações de todos os agrupamentos possíveis considerando as colunas escritas
entre parênteses. Observe:
SELECT Cod_Tipo,Cod_Linha,
Sum(Qtd_Prod) AS Qtd_Prod
FROM Produto
GROUP BY CUBE(Cod_Tipo,Cod_Linha)
GROUPING SET()
Grouping Sets vai produzir os mesmos dados que produziríamos se utilizássemos a cláusula
UNION. Como ainda não falamos de UNION, a cláusula GROUPING SETS é apresentada
neste tutorial, mas juntamente com o UNION.
CASE
A cláusula CASE é utilizada quando desejamos executar testes de condição dentro de uma
query.
-----------------------------------------------------------------------
USE [50minutos]
-----------------------------------------------------------------------
go
-----------------------------------------------------------------------
Cod_Cli int,
Nome_Cli varchar(100),
Est_Civil char(1),
Renda_Cli decimal(10,2),
Nome_Cid varchar(100)
-----------------------------------------------------------------------
(3,'José','D',5300.00,'Sorocaba')
(4,'Maria','S',6500.00,'Jundiaí')
(6,'Anita','C',500.00,'Araraquara')
(7,'Paulo','S',2500.00,'São Carlos)
(8,'Paula','S',1500.00,'São Paulo')
(9,'Roberto','V',3500.00,'São Paulo')
(10,'Roberta','S',4500.00,'São Paulo')
-----------------------------------------------------------------------
É fácil perceber o que a query abaixo vai exibir. Na tabela, na coluna Est_Civil (Estado Civil)
nós inserimos as letras S,C,D,V para (Solteiro, Casado, Divorsiado e Viúvo).
No relatório que precisamos gerar, temos que fazedr aparecer as palavras relativas ao
estado civil de cada cliente e não as letras. Não desejamos modificar os dados e nem a
estrutura da tabela, apenar queremos o relatório.
FROM Cliente
-------------------------------------------------------------------
SELECT CASE
FROM Cliente
-------------------------------------------------------------------
Note que temos duas opções de sintaxe para a utilização da cláusula CASE. A primeira
escreve uma única vez o nome da coluna Est_Civil e a segunda escreve-a várias 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 comparações um pouco mais complexas temos que
utilizar a segunda sintaxe. Um exemplo disso é o que mostramos abaixo:
SELECT Nome_Cli,
CASE
END AS Crédito
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.
Podemos utilizar a cláusula CASE também como uma opção no ORDER BY.
-- Para os clientes que têm como salário um valor <= 1000 os dados são --
apresentados ordenados pelo Nome_Cli de forma Decrescente
SELECT Cod_Cli,Nome_Cli,Sal_Cli
FROM Cliente
-----------------------------------------------------------------------
-- Apresenta os dados ordenados pela coluna Nome_Cid quando o Sexo do --- cliente
for 'F', caso contrário apresenta os dados ordenados pelo -- Nome_Est
SELECT Cod_Cli,Nome_Cli,Sal_Cli
FROM Cliente
ELSE Nome_Est
END
Muitas vezes precisamos fazer alterações nos dados com base em condições, como no caso
de aplicar um aumento na renda do cliente. Se o cliente for do sexo feminino o aumento
devera ser de 20% e se for do sexo masculino deverá ser de 10%.
UPDATE Cliente
END
END
Abaixo temos uma variação do mesmo comando, apenas acrescentamos a cláusula OUTPUT,
para exibir os dados como eles eram antes da alteração.
UPDATE Cliente
END
END
OUTPUT DELETED.*
FROM Cliente
GROUP BY Sexo_Cli
-----------------------------------------------------------------------
A CLÁUSULA UNION
-----------------------------------------------------------------------
USE [50mnutos]
-----------------------------------------------------------------------
Cod_Alu int ,
Nome_Alu varchar(100),
Ida_Alu tinyint
-----------------------------------------------------------------------
Cod_Prof int,
Nome_Prof varchar(100),
RG_Prof char(12)
-----------------------------------------------------------------------
Cod_Mestre int,
Nome_Mestre varchar(100),
DtCad_Mestre datetime,
Sal_Mestre decimal(10,2)
-----------------------------------------------------------------------
UNION
Precisamos exibir os dados das tabelas Aluno, Professor e Mestre em um único conjunto
de resultado.
-----------------------------------------------------------------------
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
-----------------------------------------------------------------------
c) Cada SELECT pode ser escrito com JOIN, Subqueries, GROUP BY e WHERE.
UNION ALL
Há uma diferença entre UNION e UNION ALL. Utilizando apenas a cláusula 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 serão exibidas, mesmo que
haja repetições.
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()
GROUPING SETS() é uma cláusula nova que pode ser substituir o UNION ALL, com uma
performance melhor, nestes casos:
UINON ALL
UNION ALL
-----------------------------------------------------------------------
Em vez de escrever tres queries nas mesma tabela como mostra o comando acima, utilize
GROUPING SETS() como segue:
FROM Mestre
INTERSECT E EXCEPT
INTERSECT é a cláusula que utilizamos para obter dados que fazem parte de duas tabelas
ao mesmo tempo (intersecção).
EXCEPT é a cláusula que utilizamos para ober dados que existem em uma tabela e não
existem em outra.
----------------------------------------------------------------------
Cod_Mestre int,
Nome_Mestre varchar(100),
DtCad_Mestre datetime,
Sal_Mestre decimal(10,2)
----------------------------------------------------------------------
INSERSECT
---------------------------------------------------------------------
EXCEPT
---------------------------------------------------------------------
EXCEPT
---------------------------------------------------------------------
Associar uma ou mais tabelas é o mesmo que liga-las através de uma ou mais colunas que
elas tenham em comum, com o objetivo de obter dados relacionado entre estas tabelas em
questão.
Existem algumas formas de associar dados dependendo do resultado que se deseja obter:
o Natural-Join
o Equi-Join
o Self Join
Suponha que voce tenha uma tabela chamada Pai e uma tabela chamada Filho com a
estrutura e dos dados apresentados logo abaixo:
PAI
FILHO
Você poderia associar estas tabelas através da a Cod_Pai (coluna que é comum às duas
tabelas) para obter dados relacionados de diversas formas:
INNER JOIN
A cláusula INNER JOIN tem como objetivo selecionar de duas ou mais tabelas apenas
- Um Natural Join ou
- Um Equi 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):
Para conseguir esta resposta será necessário relacionar as duas tabelas. Note que estas duas
tabelas se relacionam pela coluna Cod_Pai. Isto quer dizer que as duas tabelas têm a coluna
Cod_Pai e que elas possuem os mesmos valores.
Se você observar também, esta coluna comum às duas tabelas, é a chave primária da tabela
Pai e é a chave estrangeira na tabela Filho. Para obter os dados desejados execute o seguinte
comando:
IMPORTANTE: Observe que, para executar o comando acima, não é necessário 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 faça sentido para o seu sistema os dados têm que estar relacionados, ou seja, todos os
filhos têm que ter um pai existente na tabela pai. Obviamente as constraints garantem que
os dados obtidos como resposta são válidos, porque elas não permitirão que sejam
executadas operações que provoquem inconsistências 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 não se repetem,
este INNER JOIN será um Natural-Join:
o SELF JOIN
Self Join é um Inner Join de uma tabela consigo mesma. Este tipo de join apresenta
dados de um auto-relacionamento.
Note que o comando acima coloca uma chave primária na coluna Cod_Func e a chave
estrangeira, que é colocada na coluna Cod_Chefe, faz referência a coluna Cod_Func.
A tabela Funcionário armazena dados do Funcionário e o seu Chefe, sendo que um chefe
só poderá ser chefe se for antes um funcionário.
Se você observar, a coluna Cod_Chefe aceita valores nulos, para que você possa inserir
funcionários que não tenham chefe algum, ou que sejam seu próprio chefe.
1 João NULL
2 Matheus 1
3 Lucas 1
4 Pedro 2
5 Thiago 2
6 José 2
7 Tânia 1
8 Joana 3
9 Rosana 3
10 Maria 4
Para fazer o Self Join você precisa também saber escrever o alias de tabela. Isto é bem
simples:
SELECT F.Cod_Func,
F.Nom_Func,
F.Cod_Chefe
FROM Funcionario F
Muito embora não seja necessário 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 funcionários e de seus chefes voce deverá
escrever o comando abaixo, que associa a tabela Funcionário com ela mesma:
B.Nom_Func as Funcionario
ON A.Cod_Func = B.Cod_Chefe
ORDER BY 1
Note que o self join escrito acima associa a tabela Funcionário 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 também que além de utilizar o alias de tabela foi utilizado alias de coluna para facilitar
a compreenção dos dados.
Chefe Funcionário
João Matheus
João Lucas
João Tania
Lucas Joana
Lucas Rosana
Matheus José
Matheus Pedro
Matheus Thiago
LEFT JOIN
PAI
Cod_Pai Nome_Pai
FILHO
Para que você possa exibir os dados de todos os pais relacionando estes dados com os
respectivos filhos, mostrando também os dados dos pais que ainda estão sem filhos
registrados, escreva o seguinte comando:
A cláusula LEFT está sendo utilizada para mostrar todos os dados da tabela escrita do lado
esquerdo do join. O conjunto resposta obtido com a execução do comando acima é este:
Note que o SQL Server relacionou os dados como fez no caso do INNER JOIN, mas no caso
do LEFT JOIN especificamente, mostrou também os dados da tabela Pai (tabela que foi
escrita do lado esquerdo das palavras LEFT OUTER JOIN) que não se relacionaram com
nenhum filho.
Se você precisasse obter como resposta apenas os dados dos pais para os quais você ainda
não inseriu nenhum filho bastaria acrescentar ao comando a cláusula 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 situação, suponha que por algum motivo, foi necessário inserir alguns filhos
na tabela Filho, para um pai que não existe na tabela Pai. Então, para fazer isso, você
“desligou” a constraint de chave estrangeira, inseriu os dados inconsistentes e “religou” a
chave estrangeiras dizendo para o SQL Server não checar dados já existentes.
PAI
Cod_Pai Nome_Pai
FILHO
Os três últimos filhos pertencem a um pai cujo código é o número 1000 e este pai não existe
na tabela Pai.
Se você precisasse obter como resposta os dados dos filhos e seus pais, mostrando inclusive
os filhos órfãos, você precisaria escrever o seguinte comando:
Se você precisasse obter como resposta apenas os dados dos filhos para os quais você não
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
É possível que você precise ler, em apenas uma resposta, todos os dados relacionados e não
relacionados. Suponha que você precise então dos seguintes dados:
O comando que deverá ser escrito para que você receba estes dados como resposta é esse:
Se você precisasse obter como resposta apenas os dados não relacionados você
poderia escrever o comando assim:
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
1 Caderno
2 Lápis
3 Borracha
4 Caneta
Pedido
Num_Ped Data_Ped
1 24/06/2009
2 06/08/2009
SELECT Pedido.Num_Ped,
Material.Nome_Mat
FROM Pedido CROSS JOIN Material
Num_Ped Cod_Mat
1 Caderno
1 Lápis
1 Borracha
1 Caneta
2 Caderno
2 Lápis
2 Borracha
2 Caneta
Agora você deve supor que no seu sistema existam estas três tabelas:
PAI
Cod_Pai Nome_Pai
FILHO
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
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
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.
O comando acima mostra todos os pais e seus filhos e as notas destes filhos, mostra
inclusive os filhos sem nota.
O comando acima mostra todos os dados relacionados, pai com filho e filho com nota,
mostra também os pais com filhos e filhos sem nota e os pais que ainda estão sem filhos
cadastrados.
EVITANDO AMBIGUIDADE
Ambigüidade é 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 não consegui definir de qual das duas tabelas ele deve obter os dados da
coluna Cod_Pai e exibe o erro apresentado após a exibição do comando:
SELECT Cod_Pai,
Cod_Filho,
Nome_Pai,
Nome_Filho
FROM Pai INNER JOIN Filho
ON Pai.Cod_Pai = Filho.Cod_Pai
Para evitar a ambigüidade, 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
Como você deve ter percebido, é necessário 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 conteúdo destas colunas.
Caso contrário não será necessário especificar de qual tabela os dados deverão 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 ambigüidade.
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
Muitas vezes será necessário alterar os dados de uma tabela com base na existência ou não
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
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á também escrever Updates com Joins que associam mais de duas tabelas,
conforma seja necessário.
Suponha que você precisasse excluir os filhos que não receberam um respectivo pai na
tabela Pai. Para tanto, siga o mesmo raciocínio anterior. Escreva o comando delete, escreva
o select com o join, e depois retire a linha select do join, junte o update com a cláusula from
e apague os filhos órfãos.
DELETE Filho
SELECT *
FROM Pai RIGHT JOIN Filho
ON Pai.Cod_Pai = Filho.Cod_Pai
WHERE Pai.Cod_Pai IS NULL
DELETE Filho
FROM Pai RIGHT JOIN Filho
ON Pai.Cod_Pai = Filho.Cod_Pai
WHERE Pai.Cod_Pai IS NULL
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:
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 serão utilizadas as tabelas Pai e Filho (expostas logo abaixo) nas explicações e
dempostrações.
PAI
FILHO
As subqueries permitem que você obtenha dados de uma tabela com base na existência
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 função
de totalização MAX() e uma subquery:
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
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”:
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 informação, ou seja, dados que sejam do maior ou do menor valor, só
é possível quando se utiliza uma subquery.
apenas um único valor. Por exemplo, a subquery que obtém o maior valor da coluna
Idade_Pai, retorna apenas um valor – o maior.
a) Obtenha todos os dados dos pais sem mostrar o Pai mais velho:
valores de apenas uma coluna, mas poderão 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:
Suponha que você precisasse obter da tabela Pai todas as colunas apenas
dos pais que ainda NÃO possuem filhos registrados na tabela Filho. Para tanto você poderia
escrever os seguintes comandos:
O resultado obtido com o uso das subqueries podem ser obtidos pelos joins, pois os joins
apresentam melhor performance do que as subqueries:
ON Pai.Cod_Pai = Filho.Cod_Pai
SELECT Pai.*
ON Pai.Cod_Pai = Filho.Cod_Pai
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:
Para obter os dados da tabela Pai, mas apenas dos pais que não possuem um filho
correspondente na tabela Filho, você poderia escrever o seguinte comando:
Observe que nas subqueries acima, utiliza-se na cláusula Where a tabela Pai, que não foi
citada na cláusula From destas mesmas subqueries. A tabela Pai da cláusula 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 obtem 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 estão “amarradas” com a query, elas são chamadas de
Subqueries Correlacionadas.
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 também
uma coluna a mais (que não existe fisicamente na tabela Pai) que mostra a quantidade de
filhos que cada pai possui. Observe:
SELECT *,
FROM Pai
Note que a subquery acima se correlaciona com a query através da tabela Pai.
SUBSTITUINDO SUBQUERIES
1 – Para selecionar todos os pais que possuem filhos existem tres possibilidades. A últtima
apresentará melhor performance.
/* Subquey correlacionada*/
/* Inner Join*/
ON Pai.Cod_Pai = Filho.Cod_Pai
2 – Para selecionar todos os pais que não possuem filhos existem tres possibilidades. A
últtima apresentará melhor performance.
/* Subquey correlacionada*/
SELECT Pai.*
ON Pai.Cod_Pai = Filho.Cod_Pai
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:
/*Subquery Correlacionada*/
SELECT *,
FROM Pai
ON Pai.Cod_Pai = Filho.Cod_Pai
GROUP BY Pai.Cod_Pai,Pai.Nome_Pai
SUBQUERIES ANINHADAS
As subqueries aninhadas são formadas de vários comandos SELECT. Você terá uma query e
duas ou mais subqueries. Observe abaixo as tabelas utilizadas como exemplo:
CLIENTE
Cod_Cli Nome_Cli Renda_Cli
1 João Gaucho 5000,00
2 Daniel Leão 6000,00
3 Jairo Gato 3500,00
4 Roberta Zapata 5500,00
5 Helena Leitão 2500,00
CÔNJUGE
Cod_Cli Nome_Conj Renda_Conj Idade_Conj
1 Maria Souza Gaucho 2500,00 20
2 Helena Leão 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
PRODUTO
Cod_Prod Nome_Prod Qtd_Prod Val_Prod
1 Caderno 100 15.56
2 Lápis 200 1.52
3 Borracha 500 0.58
ITENS
Num_Ped Cod_Prod Qtd_Prod
1 1 50
1 2 10
2 1 30
2 2 10
2 3 5
Para obter, por exemplo, os dados de todos os cliente solteiros que já fizeram pelo menos
um pedido, você poderia escrever o seguinte somando:
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
o seguinte comando:
Você poderá alterar dados de uma tabela com base na existência de dados em outras tabelas
utilizando subqueries. Por exemplo, você poderia alterar a renda dos clientes que
compraram o produto de código 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))
Você poderá excluir dados de uma tabela com base na existência 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)