Você está na página 1de 138

1

TRANSACT - SQL

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
2

O que é Datatype.................................................................................................................................... 11

DML – SELECT, INSERT, UPDATE e DELETE ............................................................................................... 16

Utilização do comando SELECT ........................................................................................................... 16

Exibindo os dados de todas as colunas da tabela Funcionario ......................................................... 18

Utilização do comando INSERT ........................................................................................................... 32

Utilização do comando UPDATE ......................................................................................................... 42

Utilização do comando DELETE ........................................................................................................... 45

A cláusula WHERE ................................................................................................................................... 47

Critério ............................................................................................................................................ 58

Resumo ............................................................................................................................................ 58

IN / NOT IN ....................................................................................................................................... 58

BETWEEN /NOT BETWEEN ............................................................................................................. 58

LIKE / NOT LIKE / SCAPE ................................................................................................................ 58

IS NULL / IS NOT NULL .................................................................................................................... 58

A cláusula ORDER BY............................................................................................................................... 60

Ordenando pela posição da coluna ..................................................................................................... 62

Argumentos ....................................................................................................................................... 63

A cláusula TOP ........................................................................................................................................ 65

TOP n ................................................................................................................................................. 65

TOP n PERCENT .................................................................................................................................. 66

TOP n , TOP n PERCENT WITH TIES com ORDER BY.............................................................................. 67

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
3

TOP n com UPDATE e DELETE ............................................................................................................. 68

A cláusula OUTPUT ................................................................................................................................. 69

UPDATE com OUTPUT ........................................................................................................................ 71

DELETE com OUTPUT ......................................................................................................................... 72

Group By ................................................................................................................................................ 73

Funções de Totalização ...................................................................................................................... 75

Utilizando Group By ........................................................................................................................... 77

HAVING.............................................................................................................................................. 78

ROLLUP()............................................................................................................................................ 78

CUBE() ............................................................................................................................................... 79

GROUPING SET() ................................................................................................................................ 79

CASE ....................................................................................................................................................... 80

Case com SELECT................................................................................................................................ 82

Case com ORDER BY ........................................................................................................................... 84

Case com UPDATE .............................................................................................................................. 85

Case com HAVING .............................................................................................................................. 86

A cláusula UNION ................................................................................................................................... 87

UNION ............................................................................................................................................... 89

UNION ALL ......................................................................................................................................... 92

GROUPING SETS()............................................................................................................................... 93

INTERSECT e EXCEPT .......................................................................................................................... 94

Joins – Transformando dados em informação ......................................................................................... 97

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
4

INNER JOIN ...................................................................................................................................... 100

LEFT JOIN ......................................................................................................................................... 107

RIGHT JOIN ...................................................................................................................................... 110

FULL JOIN......................................................................................................................................... 113

CROSS JOIN ...................................................................................................................................... 114

Join com mais de duas tabelas.......................................................................................................... 116

Evitando Ambiguidade ..................................................................................................................... 119

UPDATE COM JOIN ........................................................................................................................... 120

DELETE COM JOIN ............................................................................................................................ 121

Joins entre tabelas que possuem Chaves Compostas ........................................................................ 122

SUBQUERY............................................................................................................................................ 124

Subquery Introduzida com Operador de Comparação ....................................................................... 127

Subquery Introduzida com IN ou NOT IN .......................................................................................... 129

Subquery Introduzida com EXISTS e NOT EXISTS ............................................................................... 131

Substituindo Subqueries................................................................................................................... 133

Subqueries Aninhadas ...................................................................................................................... 136

UPDATE COM SUBQUERY ................................................................................................................. 138

DELETE COM SUBQUERY .................................................................................................................. 138

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
5

INTRODUÇÃO

A utilização de “databases” para o armazenamentos de dados, surge nos anos 60, e o


primeiro modelo a ser utilizado foi o Hierárquico, seguidos pelos modelos Rede,
Relacionais, Dedutivo e o Objeto.

A liguaguagem SQL surge com a criação do Modelo Relacional proposta pelo Dr. Edgard
Frank Codd já nos anos 70.

O QUE SIGNIFICA A SIGLA SQL

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”.

A linguagem SEQUEL foi utilizada para demonstrar a viabilidade do modelo de


armazenamento relacional idealizado pelo Dr. Cood.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
6

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
7

Na padronização, os comandos da liguagem SQL foram agrupados de acordo com suas


funções como segue:

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 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
8

DML – DATA MANIPULATION LUANGUAGE

Na tradução, DML significa Linguagem de Manipulação da Dados, como foi dito


anteriormente, e ela abrange os comandos SELECT, INSERT, UPDATE E DELETE, ou seja,
comandos para leitura, inclusão, alteração e exclusão de dados.

Neste material, empregando a sintaxe Microsoft, exibimos a utilização detalhada da DML.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
9

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


transações.

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.

Para tanto siga as instruções abaixo:

 Clique no menu Start / Programs / Microsoft SQL Server 2008/ SQL Server
Management Studio.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
10

 Conecte-se no SQL Server, apenas clicando no botão Connect.

 Em seguida, na barra de menu, escolha a opção New Query.

 Surge para você uma área onde os comandos são digitados e executados.

 Escreva o comando abaixo para criar um database chamado 50minutos, com


todas as opções de armazenamento e dimensionamento definidas como default:

CREATE DATABASE [50minutos]

 Pressione a tecla F5 para executar o comando.

Pronto, você já tem um database criado!

 Em seguida, escreva o comando abaixo para acessar o database 50minutos,


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

USE [50minutos]

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
11

O QUE É UMA TABELA

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:

Cod_Cli Nome_Cli Renda_Cli

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
12

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:

-- Criando a tabela Cliente

CREATE TABLE Cliente

Cod_Cli int ,

Nome_Cli varchar(100) ,

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
13

Renda_Cli decimal(10,2) ,

 Na sequência, selecione apenas co comando acima e tecle F5 para executá-lo.

 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:

-- 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
apostofo, como ‘Agnaldo’ e ‘Renata’.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
14

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.

c - Você pode escrever qualquer comando da sintaxe SQL em letras maiúsculas ou


minúsculas.

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.

e – Collation é o nome que se dá ao conjunto de definiçao de idioma, ordenação,


acentuação, etc, para o armazenamento e perquisa de dados em colunas caracteres.

f – Os comentários colocados nas demonstrações sempre aparecerão na cor verde e,


podem ser escritos em apenas uma linha, utilizando para isso dois simbolos de
subtração (--), Ou poderão ser comantários de várias linhas e, para tanto deverão ser
escritos assim:

/*

Comentarios feitos

em múltiplas Linhas

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
15

são chamados de Comentários em Bloco

*/

 Nosso próximo passo será a exibição 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 são exibidos na parte inferior da sua tela.

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
16

DML – SELECT, INSERT, UPDATE E DELETE

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.

UTILIZAÇÃO DO COMANDO SELECT

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
17

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

-- Acessando o database 50minutos

Use 50minutos

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

-- Criando a tabela Funcionário

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())

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

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
18

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
19

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 não seja a da definição de sua estrutura, basta escrever o nome das colounas na
sequência em que desejar exibí-las.

-- Exibindo os dados de todas as colunas de uma tabela na sequência -- -- desejada

SELECT Sexo_Func,

Data_Func,

Cod_Func,

Nome_Func,

Sal_Func

FROM Funcionario

4 – Exibindo os dados de algunas colunas de uma tabela

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
20

Exemplo_01

-- Exibindo os dados de algumas colunas de uma tabela

-- na sequência desejada

SELECT Cod_Func,

Nome_Func,

Data_Func

FROM Funcionario

Exemplo_02

-- Exibindo os dados de algumas colunas de uma tabela

-- 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
21

É normal que os desenvolvedores de banco de dados atribuam nomes abreviados para as


colunas de suas tabelas pois é mais fácil trabalhar com nomes curtos ao escrever as queries.

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.

Estas maneiras são exibidas abaixo.

-- Atribuindo apelidos às colunas de uma tabela

-- Primeira sintaxe:

SELECT Cod_Func AS Código,

Nome_Func AS Nome,

Sexo_Func AS Sexo,

Sal_Func AS Salário,

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
22

Data_Func AS Data

FROM Funcionario

--Segunda Sintaxe:

SELECT Cod_Func Código,

Nome_Func Nome,

Sexo_Func Sexo,

Sal_Func Salário,

Data_Func Data

FROM Funcionario

-- Terceira Sintaxe:

SELECT Código = Cod_Func ,

Nome = Nome_Func ,

Sexo = Sexo_Func ,

Salário = Sal_Func ,

Data = Data_Func

FROM Funcionario

-- Quarta sintaxe:

SELECT Cod_Func AS [Código do Funcionario],

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
23

Nome_Func AS [Nome do Funcionario],

Sexo_Func AS [Sexo do Funcionario],

Sal_Func AS [Salário do Funcionario],

Data_Func AS [Data do Funcionario]

FROM Funcionario

-- Quinta Sintaxe:

SELECT Cod_Func AS "Código do Funcionario",

Nome_Func AS "Nome do Funcionario",

Sexo_Func AS "Sexo do Funcionario",

Sal_Func AS "Salário do Funcionario",

Data_Func AS "Data do Funcionario"

FROM Funcionario

-- Sexta Sintaxe:

SELECT Cod_Func AS 'Código do Funcionario',

Nome_Func AS 'Nome do Funcionario',

Sexo_Func AS 'Sexo do Funcionario',

Sal_Func AS 'Salário do Funcionario',

Data_Func AS 'Data do Funcionario'

FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
24

--Sétima Sintaxe:

SELECT Cod_Func [Código do Funcionario],

Nome_Func [Nome do Funcionario],

Sexo_Func [Sexo do Funcionario],

Sal_Func [Salário do Funcionario],

Data_Func [Data do Funcionario]

FROM Funcionario

--Oitava Sintaxe:

SELECT Cod_Func "Código do Funcionario",

Nome_Func "Nome do Funcionario",

Sexo_Func "Sexo do Funcionario",

Sal_Func "Salário do Funcionario",

Data_Func "Data do Funcionario"

FROM Funcionario

--Nona Sintaxe:

SELECT Cod_Func 'Código do Funcionario',

Nome_Func 'Nome do Funcionario',

Sexo_Func 'Sexo do Funcionario',

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
25

Sal_Func 'Salário do Funcionario',

Data_Func 'Data do Funcionario'

FROM Funcionario

-- Décima Sintaxe:

SELECT [Código do Funcionario] = Cod_Func ,

[Nome do Funcionario] = Nome_Func ,

[Sexo do Funcionario] = Sexo_Func ,

[Salário do Funcionario] = Sal_Func ,

[Data do Funcionario] = Data_Func

FROM Funcionario

-- Décima primeira Sintaxe:

SELECT "Código do Funcionario" = Cod_Func ,

"Nome do Funcionario" = Nome_Func ,

"Sexo do Funcionario" = Sexo_Func ,

"Salário do Funcionario" = Sal_Func ,

"Data do Funcionario" = Data_Func

FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
26

-- Decima Sengunda Sintaxe

SELECT 'Código do Funcionario' = Cod_Func ,

'Nome do Funcionario' = Nome_Func ,

'Sexo do Funcionario' = Sexo_Func ,

'Salário do Funcionario' = Sal_Func ,

'Data do Funcionario' = Data_Func

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.

6 – Exibindo dados de colunas virtuais

Se você observar, a tabela Funcionario não 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 ‘Basileira’ para todos as pessoas inseridas
nesta tabela.

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.

Sendo assim, basta que você execute um dos comandos abaixo:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
27

-- Exibindo todas as colunas mais uma virtual

SELECT *,'Brasileira' AS Nacionalidade

FROM Funcionario

-- Exibindo todas as colunas mais uma virtual

SELECT Cod_Func AS Código,

Nome_Func AS Nome,

Sexo_Func AS Sexo,

Sal_Func AS Salário,

Data_Func AS Data,

'Brasileira' AS Nacionalidade

FROM Funcionario

-- Exibindo algumas colunas e uma virtual

SELECT Cod_Func AS Código,

Nome_Func AS Nome,

Sexo_Func AS Sexo,

'Brasileira' AS Nacionalidade

FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
28

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.

7 – Exibindo cálculos em colunas virtuais

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.

Sendo assim, você consegue os resultados desejados escrendo o comando abaixo.

-- Exibindo aumento de salário com colunas virtuais

SELECT Cod_Func AS Código,

Nome_Func AS Nome,

Sal_Func AS [Salário Real],

Sal_Func * 1.1 AS [Salário com 10%],

Sal_Func * 1.2 AS [Salário com 20%],

'Brasileira' AS Nacionalidade

FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
29

Observe também que é possível exibir colunas virtuais como é o caso da nacionalidade e
como é o caso dos aumentos salariais num mesmo SELECT.

-- Exibindo aumentos de salário e a nacionalidade com colunas virtuais

SELECT Cod_Func AS Código,

Nome_Func AS Nome,

Sal_Func AS [Salário Real],

Sal_Func * 1.1 AS [Salário com 10%],

Sal_Func * 1.2 AS [Salário com 20%],

'Brasileira' AS Nacionalidade

FROM Funcionario

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

Para a demonstração deste tópico, 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())

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
30

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 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.

SELECT DISTINCT Sexo_Func FROM Funcionario

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.

SELECT DISTINCT Sal_Func FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
31

A query abaixo exibirá apenas uma vez os dados repetidos considerando os valores das
duas colunas a seram 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 cláusula DISTINCT para isso.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
32

UTILIZAÇÃO DO COMANDO INSERT

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.

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 cláusula:

INSERT <NomeTabela>

VALUES(valores para cada coluna separados por vírgula).

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
33

INSERT INTO <NomeTabela>

VALUES(valores para cada coluna separados por vírgula).

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:

-- 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 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
34

Observe o código abaixo:

-- Insert Posicional sem a cláusula INTO

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

-- Insert Posicional com a cláusula INTO

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

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:

-- Insert Declarativo sem a cláusula INTO

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

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
35

-- Insert Declarativo com a cláusula INTO

INSERT INTO Funcionario

(Sexo_Func,Data_Func,Cod_Func,Sal_Func, Nome_Func)

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

A utilização 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 padrão (default) se houver algum declarado para estas culunas.

Observe o código abaixo, onde estamos omitindo a inclusão de dados para a coluna
Data_Func.

INSERT Funcionario (Cod_Func,Sal_Func, Nome_Func)

VALUES(1,1000.00,'Marcos')

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
36

3 – INSERT com uma cláusula VALUES

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.

Observe que podemos utilizar ou não a cláusula INTO aqui também.

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 composição do comando SELECT com o comando INSERT é utilizada para copiar dados
de uma tabela para outra.

Podemos utilizar estes nos comandos nos seguintes casos:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
37

Caso_01 – Estruturas iguais

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.

CREATE TABLE Empregado

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

SELECT * FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
38

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.

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 Funcionário
apenas os dados que correspondem às colunas da tabela Auxiliar.

INSERT Auxiliar

SELECT Cod_Func,Nome_Func,Sexo_Func FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
39

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.

CREATE TABLE Estagiario

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:

-- Inserindo um catactere em branco na coluna Nac_Estag

INSERT Estagiario

SELECT *, ' ' FROM Funcionario

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
40

-- Inserindo a palavra ‘Brasileira’na coluna Nac_Estag

INSERT Estagiario

SELECT *, 'Brasileira' FROM Funcionario

-- Inserindo um valor Nulo na coluna Nac_Estag

INSERT Estagiario

SELECT *, Null FROM Funcionario

Poderíamos também utiilizar a palavra Default no lugar da coluna Nac_Estag, se na tabela


Estagiário houvesse um valor definido para ela. A sintaxe seria essa:

-- Inserindo o valor Default na coluna Nac_Estag

INSERT Estagiario

SELECT *, Default FROM Funcionario

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
41

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.

Então seu comando deveria ser escrito assim

-- Inserindo dados na tabela Estagiario, deixando que o próprio 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 ausência de valor!

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
42

UTILIZAÇÃO DO COMANDO UPDATE

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]

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

CREATE TABLE Pessoa

Cod_Pes int ,

Nome_Pes varchar(100) ,

Sexo_Pes char(1) ,

Sal_Pes Decimal(10,2) ,

Data_Pes Datetime ,

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
43

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

-- 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
44

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

UPDATE Pessoa

SET Nome_Pes = Nome_Pes + 'da Silva',

Sexo_Pes = 'x',

Sal_Pes = Sal_Pes + 500.00

2 – A cláusula FROM

Para o comando UPDATE a cláusula FROM é opcional. Portanto você poderia escrever os
UPDATEs anteriores assim, se quisesse:

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

-- Utilizando a cláusula FROM

UPDATE Pessoa

SET Sal_Pes = Sal_Pes * 1.1

FROM Pessoa

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
45

UPDATE Pessoa

SET Nome_Pes = Nome_Pes + 'da Silva',

Sexo_Pes = 'x',

Sal_Pes = Sal_Pes + 500.00

FROM Pessoa

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

UTILIZAÇÃO DO COMANDO DELETE

É com o comando DELETE que excluímos dados de uma tabela.

É 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)!

1 – DELETE com e sem a clásula FROM

Para o comando UPDATE a Microsoft aceita as três formas de sintaxe abaixo:

-- Excluindo dados da tabela Pessoa

DELETE Pessoa

DELETE Pessoa FROM Pessoa

DELETE FROM Pessoa

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
46

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 não
todos. Bom, neste caso você teria que utilizar a cláusula WHERE, que é o nosso
próximo assunto.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
47

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.

1 – Operadores e Critérios de Pesquisa

É 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
48

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

Use [50minutos]

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

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,'Armário','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,'Fogão','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)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
49

Os operadores de comparação são:

 Igual (=)

 Diferente (<> ou !=)

 Maior (>)

 Maior ou Igual (>=)

 Menor (<)

 Menou ou Igual (<=)

 Não Maior (!>)

 Não Menor (!<)

Vejamos alguns exemplo:

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:

SELECT * FROM Produto

WHERE Cod_Prod = 1

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
50

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 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.

Para atingir este objetivo escrevemos o comando abaixo:

SELECT * FROM Produto

WHERE Tipo_Prod = 'Cozinha'

AND Val_Prod > 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
51

Para tanto precisaríamos 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 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:

SELECT * FROM Produto

WHERE Tipo_Prod != 'Cozinha'

Ou poderá substitui-lo por este:

SELECT * FROM Produto

WHERE Tipo_Prod <> 'Cozinha'

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
52

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

SELECT * FROM Produto

WHERE Val_Prod !> 500.00

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

SELECT * FROM Produto

WHERE Val_Prod <= 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:

SELECT * FROM Produto

WHERE Cod_Prod = 2

OR Cod_Prod = 4

OR Cod_Prod = 6

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
53

Operadores para tartar conjunto de valores

Mas com se utilizar o critério de pesquisa IN poderá substituir o codigo anterior pelo que
segue e conseguirá os mesmos dados.

SELECT * FROM Produto

WHERE Cod_Prod IN (2,4,6)

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:

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)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
54

Operadores para faixas de Valores

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).

SELECT * FROM Produto

WHERE Val_Prod >= 500.00 AND Val_Prod <= 2000.00

Os mesmos dados podem ser obtidos utilizando-se o critério 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 critérios de pesquisa NOT


BETWEEEN:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
55

SELECT * FROM Produto

WHERE Val_Prod NOT BETWEEN 500.00 AND 2000.00

Operadores para tartar colunas do tipo charactere

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

SELECT * FROM Produto

WHERE Nome_Prod = '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:

-- Obtendo todos os Produtos cujo nome começa com a legra “G”.

SELECT * FROM Produto

WHERE Nome_Prod LIKE 'G%'

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
56

-- Obtendo todos os Produtos que tenha as sílabas “eira” em qualquer -- posição,


início, 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 traçinho

SELECT * FROM Produto

WHERE Nome_Prod LIKE '_____'

-- Selecione todos os Produtos, onde o nome Não comece com a letra “G”,

SELECT * FROM Produto

WHERE Nome_Prod NOT LIKE 'G%'

-- Obtendo todos os Produtos que Não tenha as sílabas “eira” em

-- qualquer posição, início, meio ou fim.

SELECT * FROM Produto

WHERE Nome_Prod NOT LIKE '%eira%'

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
57

-- 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’.

SELECT * FROM Produto

WHERE Nome_Prod LIKE '%ei_%'ESCAPE 'a'

-- O exemplo abaixo exibe os dados de todos os produtos, cujo nome não -- é 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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
58

Resumo dos Critérios de Avaliação

Critério Resumo

IN / NOT IN Pesquisa dados em uma tabela com base


na existência [ou não] dos mesmos em
uma lista de valores,

BETWEEN /NOT BETWEEN Pesquisa dados em uma tabela com base


na existência [ou não] dos mesmos em
uma faixa de valores.

LIKE / NOT LIKE / SCAPE Pesquisa dados em uma tabela,


verificando sua existência [ou não]
comparando-os com palavras ou parte
delas em uma determinada coluna. O
critério SCAPE, exclui uma ou mais letras
dos resultados desejados.

IS NULL / IS NOT NULL Pesquisa dados em uma tabela com base


na ausência [ou não] 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 também
ser utilizados para compor um critério de pesquisa mais complexo:

SELECT * FROM Produto

WHERE Nome_Prod LIKE '%A'

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
59

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 também como critérios de pesquisa as funções CONTAINS() e


FREETEXT().

c) Temos também a possibilidade de utilizar em cláusula WHERE os critérios de


pesquisa ALL, SOME | ANY e EXISTS | NOT EXISTS, mas estes são escritos com
subqueries. As subqueries são vistas no próximo tutorial.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
60

A CLÁUSULA ORDER BY

A cláusula ORDER BY é utilizada no comando SELECT com o intuito de exibir dados de


forma ordenada.

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]

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

CREATE TABLE Material

Cod_Mat int,

Tipo_Mat char(1),

Nome_Mat char(50),

Qtd_Mat int,

Val_Mat decimal(10,2)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
61

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

INSERT Material VALUES

(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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
62

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:

SELECT * FROM Material

ORDER BY Nome_Mat

ORDENANDO PELA POSIÇÃO DA COLUNA

Podemos orderna os dados a serem exibidos pelo nome da coluna ou pela posição da
mesma em duas situações.

Ordenando pela posição 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 ordenação feita
anteriormente.

SELECT * FROM Material

ORDER BY 3

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
63

Ordenando pela posicão da coluna na lista de colunas do SELECT

O comando abaixo também 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 cláusula 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.

SELECT * FROM Material

ORDER BY Nome_Mat ASC

SELECT * FROM Material

ORDER BY 3 ASC

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
64

Portanto escrevendo ASC, ou não, os dados serão apresentados com a mesma ordenação

 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 ordenação 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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
65

SELECT * FROM Material

ORDER BY 3 COLLATE Latin1_General_CI_AS_KS_WS

Obs: Resumidamente falando, collate é um conjuntos de definições referentes aos dados


armazenados em colunas do tipo caractere. O collation define, por exemplo, que uma coluna
caractere possa armazenar as letras e dígitos referentes à um determinado idioma. O
Collation define também a forma (binary ou dictionary) em que os dados são ordenados
quando um comando order by é executado sobre esta coluna. O Collation também define se
o SQL Server fará diferença, ou não, entre as letras maiúsculas e minúsculas durante uma
pesquisa, define também se ele fará diferença entre letras acentuadas ou não.

A CLÁUSULA TOP

A cláusula TOP é utilizada para apresentar os primeiros registros a serem apresentados em


uma pesquisa.

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:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
66

-- Apresenta o primeiro registro deste conjunto de dados

SELECT TOP 1 * FROM Material

-- Apresenta os dois primeiros registros deste conjunto de dados

SELECT TOP 2 * FROM Material

-- Apresenta os três primeiros registros deste conjunto de dados

SELECT TOP 3 * FROM Material

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

-- Apresenta 10% dos registro retornados por este SELECT

SELECT TOP 10 PERCERNT * FROM Material

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
67

-- Apresenta 20% dos registro retornados por este SELECT

SELECT TOP 20 PERCENT * FROM Material

TOP N , TOP N PERCENT WITH TIES COM ORDER BY

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.

O SQL Server apresenta os n primeiros registros (com base no valor absoluto ou no


percentual) trazendo os outros registros cujo valor da coluna escrita na cláusula ORDER BY
seja igual ao valor do último registro apresentado.

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.

SELECT TOP 5 WITH TIES Nome_Mat,Val_Mat FROM Material

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:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
68

-- Exibindo os materiais mais baratos da tabela

SELECT TOP 1 WITH TIES Nome_Mat,Val_Mat FROM Material

ORDER BY Val_Mat

-- Exibindo os materiais mais caros da tabela

SELECT TOP 1 WITH TIES Nome_Mat,Val_Mat FROM Material

ORDER BY Val_Mat DESC

TOP N COM UPDATE E DELETE

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.

-- Aumenta em 10% o valor dos 5 primeiros materiais da tabela

UPDATE TOP 5 Materiais

SET Val_Mat = Val_Mat 1.1

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
69

-- Exclui os 3 primeiros materiais da tabela

DELETE TOP 3 FROM Materiais

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.

“Obter os dados”quer dizer exibi-los ou salva-los em uma outra tabela.

Para exemplificar a cláusula vamos utilizar a tabela abaixo com os dados que seguem:

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

Use [50minutos]

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

CREATE TABLE Bonus

Cod_Bonus int,

Cod_Cli int,

Data_Bonus smalldatetime,

Val_Bonus decimal(10,2)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
70

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

INSERT Bonus VALUES

(1,2,Getdate(),50.00,)

(1,1,Getdate(),150.00,)

(1,3,Getdate(),80.00,)

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

CREATE TABLE Premio

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
71

UPDATE COM OUTPUT

-- Altera os dados da tabela, e exibe os dados de todas as colunas

-- com os valores anteriores à alteração

UPDATE Bonus

SET Val_Bonus = Val_Bonus * 1.1

OUTPUT DELETED.*

-- Altera os dados da tabela, e exibe os dados de todas as colunas

-- com os valores após à alteração

UPDATE Bonus

SET Val_Bonus = Val_Bonus * 1.1

OUTPUT INSERTED.*

-- Altera os dados da tabela, e exibe os valores de cod_Cli e Val_Bonus -- como eles


eram antes de ocorrer a alteração

UPDATE Bonus

SET Val_Bonus = Val_Bonus * 1.1

OUTPUT DELETED.Cod_Cli,DELETED.Val_Bonus

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
72

-- Altera os dados da tabela, e exibe os novos valores de cod_Cli e

-- Val_Bonus

UPDATE Bonus

SET Val_Bonus = Val_Bonus * 1.1

OUTPUT INSERTED.Cod_Cli,INSERTED.Val_Bonus

-- Altera os dados da tabela, mas salva os valores antigos em outra

-- tabela

UPDATE Bonus

SET Val_Bonus = Val_Bonus * 1.1

OUTPUT DELETED.* INTO Premio

DELETE COM OUTPUT

-- Exclui os dados da tabela Bonus e exibe os valores que foram

-- excluídos

DELETE Bonus OUTPUT DELETED.*;

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
73

-- Exclui os dados da tabela Bonus e exibe os valores que foram

-- excluídos

DELETE Bonus OUTPUT DELETED.Cod_Bonus, DELETED.Val_Bonus

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

-- Exclui todos os dados da tabela, mas os salva em outra tabela antes -- de excluir.

DELETE Pessoa

OUTPUT DELETED.Nome_Pes INTO Premio

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().

Para exemplificar, execute o script abaixo:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
74

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

USE [50minutos]

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

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,'Armário',300,200.00),

(5,'C',1,'Cama',500, 1000.00),

(6,'B',1,'Poltrona',100,250.00),

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
75

(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

FUNÇÃO O QUE FAZ EXEMPLO DE USO

AVG() Retorna a média dos valores de uma Avg(ExpressãoNumérica)


Expressão Numérica

COUNT() Retorna o número de linha com o Count(ExpressãoNumérica)


conteúdo diferente de Null. O seu
retorno estará no formato int.

COUNT(*) Retorna o número total de linhas Count(*)


considerando os valores nulos. O seu
retorno estará no formato int.

COUNT_BIG() Retorna o número de linha com o COUNT_BIG(ExpressãoNumérica)


conteúdo diferente de Null. O seu
retorno estará no formato Bigint.

COUNT_BIG(*) Retorna o número total de linhas COUNT_BIG(*)


considerando os valores nulos. O seu
retorno estará no formato Bigint.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
76

MAX() Retorna o maior valor de uma coluna Max(ExpressãoNumérica)

MIN() Retorna o menor valor de uma coluna Min(ExpressãoNumérica)

STDEV Retorna o desvio padrão de uma Stdev (ExpressãoNumérica)


expressão numérica. (Cálculo
Estatístico)

STDEVP() Retorna o desvio padrão populacional Dtdevp(ExpressãoNumérica)


de uma expressão numérica. (Cálculo
Estatístico)

VAR() Retorna a variação estatística de uma Var(ExpressãoNumérica)


expressão numérica. (Cálculo
Estatístico)

VARP() Retorna a variação estatística Varp(ExpressãoNumérica)


populacional de uma expressão
numérica. (Cálculo Estatístico)

GROUPING() Cria uma nova coluna no resultado de Grouping(ExpressãoNumérica)


um SELECT com as cláusulas GROUP BY
/ CUBE ou GROPUP BY/ROLLUP. A
função acrescenta o número 1 se o valor
for resultado de uma totalização e 0 se o
valor não for resultado de uma
totalização.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
77

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 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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
78

HAVING

Se quisessemos restringir o resultado apresentado no primeiro exemplo acima, ou seja, se


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, teríamos que utilizar a cláusula HAVING, como segue:

SELECT Cod_Tipo,

Sum(Qtd_Prod) AS Qtd_Prod

FROM Produto

GROUP BY Cod_Tipo

HAVING Sum(Qtd_Prod) > 500

ROLLUP()

Utilizamos para apresentar subtotais e total geral em um agrupamento de dados.

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

GROUP BY ROLLUP (Cod_Tipo,Cod_Linha)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
79

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
80

CASE

A cláusula CASE é utilizada quando desejamos executar testes de condição dentro de uma
query.

Para fazermos nossas demostrações, execute o código abaixo:

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

USE [50minutos]

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

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)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
81

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

INSERT Cliente VALUES

(1,'José Maria','C',1500.00,'São Paulo')

(2,'Maria José','S',2500.00,'São Paulo')

(3,'José','D',5300.00,'Sorocaba')

(4,'Maria','S',6500.00,'Jundiaí')

(5,'Ana','C',7600.00,'São José do Rio Preto')

(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')

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
82

CASE COM SELECT

É 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.

Para tanto, execute o código abaixo:

SELECT CASE Est_Civil

WHEN 'S' THEN 'Solteiro'

WHEN 'C' THEN 'Casado'

WHEN 'D' THEN 'Divorsiado'

WHEN 'V' THEN 'Viúvo'

ELSE 'Estado Civil inexistente'

END AS [Estado Civil]

FROM Cliente

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
83

SELECT CASE

WHEN Est_Civil = 'S' THEN 'Solteiro'

WHEN Est_Civil = 'C' THEN 'Casado'

WHEN Est_Civil = 'D' THEN 'Divorsiado'

WHEN Est_Civil = 'V' THEN 'Viúvo'

ELSE 'Estado Civil inexistente'

END AS [Estado Civil]

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

WHEN Renda_Cli <= 1000 THEN 'Crédito de 500.00'

WHEN Renda_Cli Between 1000 And 2000 THEN 'Crédito de 800.00'

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
84

ELSE 'Credito Aprovado'

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.

CASE COM ORDER BY

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

-- Para os salários que forem inferiores a 1000.00 os dados são

-- apresentados ordenados de forma crescente também pelo Nome_Cli

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

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
85

-- 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

ORDER BY CASE Sexo_Cli WHEN 'F' THEN Nome_Cid

ELSE Nome_Est

END

CASE COM UPDATE

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

SET Renda_Cli = CASE Sexo_Cli = 'F' THEN Renda_Cli * 1.2

ELSE Renda_Cli * 1.1

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
86

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 = 'São Paulo'

CASE COM HAVING

Também podemos restringir os dados de um agrupamento que serão apresentados


utilizando a cláusula CASE juntamente com HAVING.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
87

-- 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 serão considerados

-- Se o cliente for do sexo = 'M' apenas os dados com Renda_Cli >

-- 1000.00 serão 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 CLÁUSULA UNION

Muitas vezes precisamos exibir dados de várias tabelas transformando-os em um único


conjunto de informação. Para tanto, temos alguns comandos que podem ser utilizados,
dependendo obviamente, de como precisamos exibir a informação.

Para esta demonstração execute o script abaixo:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
88

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

USE [50mnutos]

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

CREATE TABLE Aluno

Cod_Alu int ,

Nome_Alu varchar(100),

Ida_Alu tinyint

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')

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
89

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 cláusula UNION podemos conseguir atingir este objetivo. Observe:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
90

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

SELECT Cod_Alu AS Código,

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,

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
91

' ',

DTCad_Mestre

FROM Mestre

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

Note que a utilizaçao da cáusula UNION tem algumas regras:

a) Todos os SELECTs utilizados deverão 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 relatório 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 cláusula ORDER BY deve ser escrita no


final, em ultimo lugar.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
92

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.

Valem para UNION ALL, as mesmas regras do UNION.

SELECT Cod_Alu AS Código,

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,

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
93

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:

SELECT Count(Cod_Mestre) FROM Mestre

UINON ALL

SELECT Avg(DTCad_Mestre) FROM Mestre

UNION ALL

SELECT Sum(Sal_Mestre) FROM Mestre

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
94

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

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 cláusulas 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 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.

Observe o udo das duas cláusulas (INTERSECT e EXCEPT):

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
95

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

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)

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

-- INTERSECÇAO: 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

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
96

-- EXCEÇÃO: O que tem em uma tabela e não tem na outra

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

-- Aparecerá só os dados do mestre de código 2, chamado Paula.

SELECT * FROM Mestre

EXCEPT

SELECT * FROM Mestre_Historico

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

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

-- Aparecerá só os dados do mestre de código 1000, chamado Ricardo.

SELECT * FROM Mestre_Historico

EXCEPT

SELECT * FROM Mestre

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
97

JOINS – TRANSFORMANDO DADOS EM INFORMAÇÃO

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:

 INNER JOIN ou JOIN - Apenas dados Relacionados

o Natural-Join

o Equi-Join

o Self Join

 OUTER JOIN – Dados Relacionados e não Relacionados

o Left Outer Join ou Left Join

o Right Outer Join ou Right Join

o Full Outer Join ou Full Join

 CROSS JOIN – Produto Cartesiano

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
98

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’))

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
99

PAI

Cod_Pai Nome_Pai Idade_Pai

1 Daniel de Souza Leão Sobrinho 62

2 Agnaldo Diogo dos Santos 38

3 Fernando de Oliveira Leão 36

FILHO

Cod_Filho Cod_Pai Nome_Filho Sexo_Filho

1 1 Renata de Oliveira Leão F

2 1 Fernando de Oliveira Leão M

3 1 Roberta de Oliveira Leão F

3 1 Jairo de Oliveira Leão M

4 2 Bruno Ferreira dos Sandos M

5 2 Antonio dos Santos Neto M

6 2 Pedro Ferreira dos Santos M

7 3 Lucar Ribeiro Leão M

8 3 Helder Riberito Leão M

9 4 Mateus Ribeiro Leão M

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
100

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

os dados relacionados entre todas elas. Um INNER JOIN poderá ser:

- Um Natural Join ou

- Um Equi Join

o 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):

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
101

Nome do Pai Nome do Filho Sexo

Daniel de Souza Leão Sobrinho Renata de Oliveira Leão F

Daniel de Souza Leão Sobrinho Fernando de Oliveira Leão M

Daniel de Souza Leão Sobrinho Roberta de Oliveira Leão F

Daniel de Souza Leão Sobrinho Jairo de Oliveira Leão M

Agnaldo Diogo dos Santos Bruno Ferreira dos Santos M

Agnaldo Diogo dos Santos Antonio dos Santos Neto M

Agnaldo Diogo dos Santos Pedro Ferreira dos Santos M

Fernando de Oliveira Leão Lucas Ribeiro Leão M

Fernando de Oliveira Leão Helder Ribeiro Leão M

Fernando de Oliveira Leão Mateus Ribeiro Leão M

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:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
102

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:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
103

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 primária da mesma tabela. Observe o caso da tabela
funcionário 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 primária na coluna Cod_Func e a chave
estrangeira, que é colocada na coluna Cod_Chefe, faz referência a coluna Cod_Func.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
104

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.

Veja a tabela com dados:

Cod_Func Nom_Func Cod_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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
105

Você oportunidade, em tópicos anteriores, de aprender a colocar Alias na colunas das


tabelas em um Select para obter dados com uma visualização meis amigável, ou seja para
poder visualizar as colunas com um título diferente do armazenado na tabela.

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:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
106

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.

Ao executar o comando anterior você obtém a seguinte resposta:

Chefe Funcionário

João Matheus

João Lucas

João Tania

Lucas Joana

Lucas Rosana

Matheus José

Matheus Pedro

Matheus Thiago

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
107

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 não foi registrado nenhum filho na tabela
Filho. Esta situação não representa um erro, porque é necessário registrar primeiro o pai
para depois inserir seus filhos. Neste caso, suponha que você inseriu o Pai cujo código é o
número 4 e que ainda não colocou nenhum filho para ele. Observe a demonstração abaixo:

PAI

Cod_Pai Nome_Pai

1 Daniel de Souza Leão Sobrinho

2 Agnaldo Diogo dos Santos

3 Fernando de Oliveira Leão

4 Jairo de Oliveira Leão

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
108

FILHO

Cod_Filho Cod_Pai Nome_Filho Sexo_Filho

1 1 Renata de Oliveira Leão F

2 1 Fernando de Oliveira Leão M

3 1 Roberta de Oliveira Leão F

3 1 Jairo de Oliveira Leão 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 Leão M

8 3 Helder Ribeiro Leão M

9 3 Mateus Ribeiro Leão M

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:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
109

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:

Nome do Pai Nome do Filho Sexo

Daniel de Souza Leão Sobrinho Renata de Oliveira Leão F

Daniel de Souza Leão Sobrinho Fernando de Oliveira Leão M

Daniel de Souza Leão Sobrinho Roberta de Oliveira Leão F

Daniel de Souza Leão Sobrinho Jairo de Oliveira Leão 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 Leão Lucar Ribeiro Leão M

Fernando de Oliveira Leão Helder Ribeiro Leão M

Fernando de Oliveira Leão Mateus Ribeiro Leão M

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
110

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.

Suponha, então, que seus dados ficaram desta forma:

PAI

Cod_Pai Nome_Pai

1 Daniel de Souza Leão Sobrinho

2 Agnaldo Diogo dos Santos

3 Fernando de Oliveira Leão

4 Jairo de Oliveira Leão

FILHO

Cod_Filho Cod_Pai Nome_Filho Sexo_Filho

1 1 Renata de Oliveira Leão F

2 1 Fernando de Oliveira Leão M

3 1 Roberta de Oliveira Leão F

3 1 Jairo de Oliveira Leão M

4 2 Bruno Ferreira dos Santos M

5 2 Antonio dos Santos Neto M

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
111

6 2 Pedro Ferreira dos Santos M

7 3 Lucas Ribeiro Leão M

8 3 Helder Ribeiro Leão M

9 3 Mateus Ribeiro Leão M

10 1000 Sandra Rosa Madalena F

11 1000 Margarida Paula Regina F

12 1000 Ana Maria Cristina F

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:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
112

Nome do Pai Nome do Filho Sexo

Daniel de Souza Leão Sobrinho Renata de Oliveira Leão F

Daniel de Souza Leão Sobrinho Fernando de Oliveira Leão M

Daniel de Souza Leão Sobrinho Roberta de Oliveira Leão F

Daniel de Souza Leão Sobrinho Jairo de Oliveira Leão 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 Leão Lucar Ribeiro Leão M

Fernando de Oliveira Leão Helder Ribeiro Leão M

Fernando de Oliveira Leão Mateus Ribeiro Leão 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ê 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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
113

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:

Nome do Pai Nome do Filho Sexo

Daniel de Souza Leão Sobrinho Renata de Oliveira Leão F

Daniel de Souza Leão Sobrinho Fernando de Oliveira Leão M

Daniel de Souza Leão Sobrinho Roberta de Oliveira Leão F

Daniel de Souza Leão Sobrinho Jairo de Oliveira Leão 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 Leão Lucar Ribeiro Leão M

Fernando de Oliveira Leão Helder Ribeiro Leão M

Fernando de Oliveira Leão Mateus Ribeiro Leão M

Jairo de Oliveira Leão NULL NULL

Null Sandra Rosa Madalena F

Null Margarida Paula Regina F

Null Ana Maria Cristina F

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
114

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 não 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
1 Caderno
2 Lápis
3 Borracha
4 Caneta

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
115

Pedido
Num_Ped Data_Ped
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ê obtém como resposta são os seguintes:

Num_Ped Cod_Mat
1 Caderno
1 Lápis
1 Borracha
1 Caneta
2 Caderno
2 Lápis
2 Borracha
2 Caneta

Em todos os pedidos foram vendidos uma determinada quantidade de todos os materiais.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
116

JOIN COM MAIS DE DUAS TABELAS

Agora você deve supor que no seu sistema existam estas três tabelas:

PAI

Cod_Pai Nome_Pai

1 Daniel de Souza Leão Sobrinho

2 Agnaldo Diogo dos Santos

3 Fernando de Oliveira Leão

4 Jairo de Oliveira Leão

FILHO

Cod_Filho Cod_Pai Nome_Filho Sexo_Filho

1 1 Renata de Oliveira Leão F

2 1 Fernando de Oliveira Leão M

3 1 Roberta de Oliveira Leão F

3 1 Jairo de Oliveira Leão M

4 2 Bruno Ferreira dos Santos M

5 2 Antonio dos Santos Neto M

6 2 Pedro Ferreira dos Santos M

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
117

7 3 Lucas Ribeiro Leão M

8 3 Helder Ribeiro Leão M

9 3 Mateus Ribeiro Leão 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
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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
118

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

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
119

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

Server: Msg 209, Level 16, State 1, Line 1


Ambiguous column name '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

Desta forma não ocorrerá mais o erro de número 209.

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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
120

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

UPDATE COM JOIN

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
121

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á também escrever Updates com Joins que associam mais de duas tabelas,
conforma seja necessário.

DELETE COM JOIN

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
122

Execute este comando após 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,

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:

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
123

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
124

SUBQUERY

Neste assunto serão utilizadas as tabelas Pai e Filho (expostas logo abaixo) nas explicações e
dempostrações.

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’))

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
125

PAI

Cod_Pai Nome_Pai Idade_Pai

1 Daniel de Souza Leão Sobrinho 69

2 Agnaldo Diogo dos Santos 43

3 Fernando de Oliveira Leão 42

4 Jairo de oliveira Leão 39

FILHO

Cod_Filho Cod_Pai Nome_Filho Sexo_Filho

1 1 Renata de Oliveira Leão F

2 1 Fernando de Oliveira Leão M

3 1 Roberta de Oliveira Leão F

3 1 Jairo de Oliveira Leão 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 Leão M

8 3 Helder Ribeiro Leão M

9 3 Mateus Ribeiro Leão M

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
126

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:

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 Leão 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”.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
127

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 informação, ou seja, dados que sejam do maior ou do menor valor, só
é possível quando se utiliza uma subquery.

SUBQUERY INTRODUZIDA COM O PERADOR DE COMPARAÇÃO

As subqueries introduzidas com os operadores de comparação devem retornar sempre

apenas um único valor. Por exemplo, a subquery que obtém o maior valor da coluna
Idade_Pai, retorna apenas um valor – o maior.

Você poderia utilizar outros sinais de comparação, como por exemplo:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
128

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)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
129

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 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:

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 NÃO 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)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
130

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:

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
131

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 não 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 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.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
132

Justamente porque estas subqueries estão “amarradas” com a query, elas são chamadas de
Subqueries Correlacionadas.

As Subqueries Correlacionadas normalmente consomem muitos recursos do sistema para


serem processadas, portanto sempre dê preferencia para obter seus dados escrevendo
joins que têm um melhor processamento.

É interessante que você conheça as subqueries para poder interpretá-las quando


necessário.

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 *,

(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 através da tabela Pai.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
133

SUBSTITUINDO SUBQUERIES

1 – Para selecionar todos os pais que possuem filhos existem tres possibilidades. A últtima
apresentará melhor performance.

/* Subquey correlacionada*/

SELECT * FROM Pai

WHERE EXISTS (SELECT Cod_Pai FROM Filho

WHERE Filho.Cod_Pai = Pai.Cod_Pai)

/* Subquery não correlacionada*/

SELECT * FROM Pai

WHERE Cod_Pai IN (SELECT Cod_Pai FROM Filho)

/* Inner Join*/

SELECT DISTINCT Pai.*

FROM Pai INNER JOIN Filho

ON Pai.Cod_Pai = Filho.Cod_Pai

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
134

2 – Para selecionar todos os pais que não possuem filhos existem tres 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 não 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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
135

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 *,

(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 função de totalização 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ó é perceptível quando as tabelas possuem uma quantidade


razoável de dados.

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
136

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

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
137

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:

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
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))

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br
138

UPDATE COM SUBQUERY

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))

DELETE COM SUBQUERY

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)

Rua Domingos de Moraes, 770, bloco 2, conjunto 9


Vila Mariana - São Paulo - SP
11 2361 3050 | 11 2361 4050
contato@50minutos.com.br

Você também pode gostar