Sei sulla pagina 1di 39

FALS – BANCO DE DADOS 1

Curso: Banco de Dados

FALS

Apostila – Parte 1

Professor: Paulo Roberto Tazinazo Cândido

Página 1 de 39
FALS – BANCO DE DADOS 1

I. Introdução a Banco de Dado Relacional ................................................................ 3


A. Criando Tabelas – Conceitos Básicos ................................................................ 4
1. Primeira versão da tabela de clientes .............................................................. 4
B. Nome completo e parcial. .................................................................................. 5
C. Exclusão de uma tabela do banco de dados ........................................................ 5
D. Manipulação Básica de Dados ........................................................................... 6
1. Inserindo dados na tabela de Clientes ............................................................. 6
2. Recuperar (ler) dados de uma tabela .............................................................. 6
3. Exclusão de Linhas ........................................................................................ 8
4. Alteração de valores de colunas ..................................................................... 8
II. Tipos de dados. ..................................................................................................... 9
A. Tipos providos pelo sistema............................................................................... 9
B. Tipos criados pelo usuário ............................................................................... 11
C. Visualizando definição de tabelas e tipos criados pelo usuário ......................... 11
III. Incluindo e excluindo colunas de uma tabela ................................................... 12
A. Incluindo uma coluna. ..................................................................................... 12
B. Excluindo uma coluna ..................................................................................... 12
IV. Colunas Identity .............................................................................................. 12
V. Integridade de Dados ........................................................................................... 13
A. CHECK ........................................................................................................... 14
B. DEFAULT ...................................................................................................... 15
C. PRIMARY KEY ............................................................................................. 16
D. UNIQUE ......................................................................................................... 18
E. REVISÃO 1 .................................................................................................... 18
F. FOREIGN KEY .............................................................................................. 19
G. Habilitar e desabilitar constraints ..................................................................... 21
H. Criar constraints sem que os dados existentes na tabela sejam verificados ....... 21
VI. SELECT Avançado ......................................................................................... 22
A. Consultas com JOIN ........................................................................................ 22
B. USO DE APELIDO......................................................................................... 24
C. INNER JOIN ................................................................................................... 24
D. LEFT JOIN ..................................................................................................... 25
E. RIGHT JOIN ................................................................................................... 25
F. JOIN DE UMA TABELA COM ELA MESMA .............................................. 26
G. SUBQUERY ................................................................................................... 27
H. EXISTS ........................................................................................................... 28
VII. GERAR INFORMAÇÕES SUMARIZADAS ................................................. 29
A. EXEMPLOS ................................................................................................... 29
B. GROUP BY .................................................................................................... 30
C. HAVING ......................................................................................................... 31
D. COMPUTE e COMPUTE BY ......................................................................... 32

Página 2 de 39
FALS – BANCO DE DADOS 1

I. Introdução a Banco de Dado Relacional


Cada um dos diferentes modelos de banco de dados é caracterizado pela forma (ou
estrutura) utilizada para armazenamento de dados e implementação de ligações entre os
mesmos. Nos Bancos de Dados Relacionais são utilizadas tabelas bidimensionais,
também chamadas de relações, para armazenamento dados. Tais tabelas são organizadas
em linhas e colunas, conforme exemplo abaixo utilizado para armazenar dados sobre
funcionários de uma empresa.

Numero_Matrícula Nome_Funcionário Salário Idade


1000 Paulo 1000,00 20
1010 Maria 5000,00 45
2045 João 800,00 38

Note que cada linha representa um elemento do conjunto dos funcionários da empresa e
cada coluna, uma dada informação a respeito dos funcionários. Desta forma, cada célula
da tabela armazena um dado referente a um funcionário específico. Maria tem 45 anos
de idade.

As tabelas (ou relações) possuem as seguintes propriedades (extraídas do livro do


professor Setzer):
1) Cada célula de uma tabela pode ser vazia (nula;NULL) ou, ao contrário, conter no
máximo um valor;
2) A ordem das linhas é irrelevante (do ponto de vista do usuário);
3) Não deve haver duas linhas iguais;
4) Cada coluna tem um nome;
5) Duas colunas distintas devem ter nomes diferentes;
6) Usando-se os nomes para fazer referencia às colunas, a ordem destas é irrelevante;
7) Cada tabela recebe um nome próprio , distinto do nome de qualquer outra tabela do
banco (ou base) de dados;
8) Os valores de uma coluna são retirados todos de um mesmo conjunto, denominado
domínio da coluna;
9) Duas ou mais colunas distintas podem ser definidas sobre o mesmo domínio.

Página 3 de 39
FALS – BANCO DE DADOS 1

A. Criando Tabelas – Conceitos Básicos

Apresentamos a seguir o comando SQL utilizado para criar a tabela que armazena dados
sobre os clientes de uma empresa.

1. Primeira versão da tabela de clientes

A seguir a descrição das colunas da tabela de clientes.

Coluna Descrição Domínio


Codigo Cliente Código interno criado para cada número inteiro – quantidade
cliente estimada máxima de 20.000
clientes
Nome Cliente Nome ou razão social do cliente texto de no máximo 50
caracteres
Data Cadastro Data em que o cliente foi Dia, mês e ano do cadastro
cadastrado
Estado Estado em que o cliente reside RS, SC, PR (todos os clien. são
da região sul)
Telefone Telefone do cliente O cliente pode não ter telefone
Media Compras Média de compras realizadas Valor expresso em R$
pelo cliente por mês
Física/Jurídica Pessoa física ou jurídica 0 = física; 1 = jurídica

A seguir o comando SQL para criação da tabela CLIENTE.


create table dbo.tbcliente (
CodCliente int not null,
NomeCliente varchar(50) not null,
DataCadastro datetime not null,
Estado char(2) not null,
Telefone char(15) null,
MediaCompra money not null,
FisJur int not null
)

No comando acima, definiu-se o nome da tabela como “dbo.tbcliente”. Para cada coluna
é necessário especificar seu nome, seu tipo (domínio) e se será ou não permitido o valor
nulo (NULL).

Os tipos utilizados foram:


§ int : número inteiro entre -2.147.483.648 e 2.147.483.647
§ varchar e char : texto alfanumérico - cadeia de caracteres
§ datetime : data e hora
§ money : valores monetários

Uma descrição detalhada destes e outros tipos de dados nativos do MS SQL-Server


serão estudados a seguir.

Página 4 de 39
FALS – BANCO DE DADOS 1

B. Nome completo e parcial.

Nomes de tabelas e outros objetos no MS SQL Server seguem a seguinte estrutura:

Nome Completo: servidor.database.owner.table_name

Nome Parcial : database.owner.table_name


owner.table_name
table_name

Servidor = nome do servidor


Database = nome do database
Owner = proprietário da tabela (conta de usuário do database)
Table_name = nome da tabela ou objeto.

Quando um nome parcial é utilizado, o sistema completa as partes faltantes com base no
contexto em que o comando está sendo executado. Por exemplo, se for utilizado o nome
parcial table_name, o sistema utilizará para completar o nome do objeto o nome do
servidor onde se está executando o comando, o nome do database corrente e o nome da
conta do usuário que esta executando o comando.

IMPORTANTE: É extremamente recomendável que todos os objetos de um database


tenham o mesmo proprietário (owner). Veremos melhor o porquê disto quando
estudarmos dependência entre objetos do database.

C. Exclusão de uma tabela do banco de dados

O comando a seguir elimina definitivamente a tabela DBO.TBCLIENTE do database


corrente.
drop table dbo.tbcliente

Página 5 de 39
FALS – BANCO DE DADOS 1

D. Manipulação Básica de Dados

Execute os comandos abaixo no MS SQL Server para visualizar os resultados. Não se


esqueça de criar a tabela de clientes primeiro.

1. Inserindo dados na tabela de Clientes

Atribuindo valores para todos as colunas da tabela, na ordem em que foram definidas
pelo comando CREATE TABLE
insert tbcliente
values (100,'Ana','11/20/2001','RS','1234-5678',2000.20,0)

insert tbcliente
values (110,'Joao','03/05/1999','SC',null,120.33,0)

Atribuindo valores apenas para as colunas obrigatórios (NOT NULL) e em qualquer


ordem.
insert tbcliente
(CodCliente,NomeCliente,DataCadastro,Estado,MediaCompra,FisJur)
values (120 , 'RGB' , '01/07/2002' , 'PR' , 481.45 , 1)

insert tbcliente
(NomeCliente,DataCadastro,Estado,CodCliente,MediaCompra,FisJur)
values ('JRS' , '08/17/1987' , 'PR' , 130, 1000000.19 , 1)

2. Recuperar (ler) dados de uma tabela

Listando todas as linhas e todos as colunas.


select * from tbcliente

Listando todas as linhas e algumas colunas


select NomeCliente, MediaCompra
from tbcliente

Alterando os cabeçalho de coluna na listagem gerada pelo comando select. Quando


existirem brancos, deve-se utilizar [].
select NomeCliente as Nome_Cliente,
MediaCompra as [Media Compra Mensal],
[Data Cadastro] = DataCadastro
from tbcliente

Página 6 de 39
FALS – BANCO DE DADOS 1

Classificando (ordenando) o resultado em ordem crescente pelos valores da coluna


NomeCliente
select NomeCliente as Nome_Cliente,
MediaCompra as [Media Compra Mensal],
[Data Cadastro] = DataCadastro
from tbcliente
order by NomeCliente asc

asc é o padrão, portanto não precisaria ter sido utilizado.

Classificando (ordenando) o resultado em ordem decrescente pela coluna MediaCompra


select NomeCliente as Nome_Cliente,
MediaCompra as [Media Compra Mensal],
[Data Cadastro] = DataCadastro
from tbcliente
order by 2 desc

O número 2 específica que a classificação deve ser feita pela segunda coluna ou seja
MediaCompra. Poderíamos ter escrito “order by MediaCompra desc”, o resultado seria
o mesmo.

Modificando a consulta (query) anterior, para listar apenas os 3 melhores clientes.


select top 3
NomeCliente as Nome_Cliente,
MediaCompra as [Media Compra Mensal],
[Data Cadastro] = DataCadastro
from tbcliente
order by 2 desc

TOP 3 especifica que apenas as três primeiras linhas do resultado serão apresentadas.

Selecionando linhas.
Listar, em ordem decrescente por Estado e Nome do cliente, apenas as pessoas físicas.
select NomeCliente as Nome_Cliente,
MediaCompra as [Media Compra Mensal],
[Data Cadastro] = DataCadastro,
Estado
from tbcliente
where FisJur=0
order by 4,NomeCliente desc

Apenas as linhas que satisfizerem a condição da cláusula WHERE serão apresentadas


no resultado. Pode se utilizar conectivos lógicos (and , or e not) para produzir
expressões lógicas compostas.

Página 7 de 39
FALS – BANCO DE DADOS 1

3. Exclusão de Linhas

Excluir todas as linhas de uma tabela. Exclui apenas o conteúdo, a tabela continua
existindo no database, vazia.
delete tbcliente

Outra forma.
truncate table tbcliente

Mais rápido. Apenas usuários com previlégio de proprietário (db_owner) podem


executar este comando.

Excluir apenas algumas linhas


Excluir de tbcliente todos os clientes com média de compras mensal inferior a R$500,00
delete tbcliente
where MediaCompra < 500

Apenas linhas que satisfizerem a condições da cláusula WHERE serão excluídas.

4. Alteração de valores de colunas

O cliente RGB mudou-se para o RS e sua média de compras passou de R$481,45 para
R$356,34.
update tbcliente
set estado='RS', MediaCompra=356.34
where codcliente=120

Se você não colocar a cláusula WHERE, todas as linhas da tabela terão os valores das
colunas Estado e MediaCompra alterados. CUIDADO.

Página 8 de 39
FALS – BANCO DE DADOS 1

II. Tipos de dados.


A. Tipos providos pelo sistema

Tipo Descrição Tamanho


BIT Número inteiro 0 ou 1 1 Bit
TINYINT Números inteiros entre 0 e 255 1 Byte
SMALLINT Números inteiros entre –32.768 e 32.767 2 Bytes
INT Números inteiros entre –2.147.483.648 e 4 Bytes
+2.147.483.647
DECIMAL(P,S) ou Números com tamanho máximo (precisão - Depende da
NUMERIC(P,S) P) e números de casas decimais (escala - S) precisão (P):
especificadas da seguinte forma: P Bytes
DECIMAL(P,S). Por exemplo, o número 1–9 5
12345,678, que tem 8 dígitos (P), sendo 3 10-19 9
decimais (S), pode ser armazenado em uma 20-28 13
coluna de uma tabela de tipo: 29-38 17
DECIMAL(8,3). Por padrão a maior
precisão é de 28. Alternativamente o Sql
Server pode ser configurado para até a
precisão 38. 0 <= S <= P
MONEY Valores monetarios entre 8 Bytes
-922.337.203.685.477,5808 e
+922.337.203.685.477,5807
SMALLMONEY Valores monetarios entre –214.748,3648 e 4 Bytes
+214.748,3647
FLOAT(N) Números reais na notação ponto flutuante. Depende de N
Pode, opcionalmente, ser especificado o N Precisão
número de bits (N) a serem utilizados para Bytes
armazenar a mantissa do número em 1-24 7dig 4
notação científica, por exemplo: float(24). 25-53 15dig 8
Float(53) é equivalente a precisão dupla
(double). Mais utilizado em aplicações
científicas e de engenharia. Números entre
– 1,79E + 308 e 1,79E + 308
REAL Mesmo que float(24) 4 Bytes
DATETIME Data e hora entre 01/01/1753 e 31/12/9999, 8 Bytes
com precisão de 3.33 milesegundos.
SMALLDATETIME Data e hora entre 01/01/1900 e 06/06/2079, 4 Bytes
com precisão de 1 segundo.
CHAR(N) Strings de caracteres de tamanho fixo. N Bytes
Tamanho (N) máximo 8000 caracteres
VARCHAR(N) Strings de caracteres de tamanho variável. N Bytes ou
Tamanho (N) máximo 8000 caracteres. menos,
dependendo do
tamanho do dado
armazenado)

Página 9 de 39
FALS – BANCO DE DADOS 1

TEXT Texto de até 2.147.483.647 caracteres. Tamanho do


texto
NCHAR(N) Strings de caracteres UNICODE de N*2 Bytes
tamanho fixo. Tamanho (N) máximo 4000
caracteres
NVARCHAR(N) Strings de caracteres UNICODE de N*2 Bytes ou
tamanho variável. Tamanho (N) máximo menos,
4000 caracteres. dependendo do
tamanho do dado
armazenado)
NTEXT Texto de até 1.073.741.823 caracteres. Tamanho do
texto * 2
BINARY(N) Strings binárias de tamanho fixo. Máximo N
de 8000 bytes.
VARBINARY Strings binárias de tamanho VARIÁVEL. N ou menos,
Máximo de 8000 bytes. dependendo do
dado
armazenado.
IMAGE Campo binário de até 2.147.483.647 bytes. Tamanho da
Utilizado para armazenar imagens. imagem.
CURSOR Utilizado em programação. Permite navegar
por um conjunto de registros oriundos de
uma consulta (query). Não pode ser
utilizado como tipo de coluna de tabelas.
TIMESTAMP Utilizado internamente pelo Sql Server no 8 Bytes
processo de Recovery (veremos
futuramente). Pode ser utilizado como tipo
de coluna de tabelas. Quando uma linha é
inserida, o Sql Server gera automaticamente
um valor para a coluna. Quando uma linha é
alterada, o valor da coluna timestamp é
alterado. Nunca utilizar colunas timestamp
em chaves, especialmente chaves primárias.
UNIQUEIDENTIFIER Usado para armazenar GUID (globally 16 Bytes
unique identification number). GUID são
números binários com garantia de serem
únicos, nenhum computador no mundo
pode gerar um GUID igual a um já
existente. Utiliza-se a função NEWID para
gerá-los. Utilizado para atribuir um
identificador que seja único dentro de uma
rede de computadores.

Página 10 de 39
FALS – BANCO DE DADOS 1

Exercício

Crie a tabela descrita abaixo, para armazenamento de dados sobre veículos à venda em
uma agência de automóveis, utilizando sempre o tipo mais adequado. Treine na tabela
criada os comando INSERT, SELECT, DELETE e UPDATE.

Nome da tabela: Automóvel


Colunas:

Nome Coluna Descrição


Marca Máximo de 15 caracteres
Modelo Máximo de 10 caracteres
Potencia Número com no máximo 2 casas inteiras e 3
decimais
Velocidade_Maxima Número inteiro de no máximo 500.
Preço Valor monetário de no máximo R$200.000,00
Data_Fabricacao Dia, mês e ano de fabricação do veículo. Datas
pertencentes aos anos de 1950 a 2050.
Numero_Donos Número de proprietários que o veículo já teve.
Máximo 100.

B. Tipos criados pelo usuário

São tipos de dados definidos pelos usuários (desenvolvedores) com base nos tipos
fornecidos pelo sistema.

A criação e a exclusão de tipos definidos pelo usuário são executadas através de System
Stored Procedure: programas definidos pelo sistema. Futuramente veremos quais são as
procedures mais utilizadas e como criar nossas próprias. Os nomes de todas as System
Stored Procedures começam com SP_.

exec sp_addtype cep, 'char(10)' -- cria o tipo CEP


create table dbo.teste ( rua varchar(100) not null, cep cep not null ) -- cria tabela
drop table dbo.teste -- apaga tabela
exec sp_droptype cep -- apaga tipo definido pelo usuário

C. Visualizando definição de tabelas e tipos criados pelo


usuário

Se você necessitar visualizar a estrutura de uma tabela, isto é, quais são suas colunas e
respectivos tipos e propriedades (você perdeu o arquivo onde estava o comando Create
Table), utilize a System Stored Procedure SP_HELP, da seguinte forma.

EXEC SP_HELP NOME_TABELA

Página 11 de 39
FALS – BANCO DE DADOS 1

Uma listagem com todas as informações referentes à estrutura da tabela será


apresentada.

A procedure SP_HELP também pode ser utilizada para visualizar informações sobre
tipos de dados criados pelo usuário, por exemplo:

EXEC SP_HELP CEP

III.Incluindo e excluindo colunas de uma tabela


Com o comando ALTER TABLE é possível alterar a definição (estrutura) de uma
tabela, incluindo ou excluindo colunas na mesma (também é possível definir
CONSTRAINT – veremos a seguir).

A. Incluindo uma coluna.

ALTER TABLE TBCLIENTE ADD DATA_NASCIMENTO DATETIME NULL

O exemplo acima inclui a coluna DATA_NASCIMENTO na tabela TBCLIENTE.

Observação: Se a tabela contiver dados, só será possível incluir uma coluna com o
atributo NULL; a menos que a definição da coluna possua uma constraint DEFAULT (
veremos constraints a seguir).

B. Excluindo uma coluna

ALTER TABLE TBCLIENTE DROP COLUMN DATA_NASCIMENTO

O exemplo acima exclui a coluna DATA_NASCIMENTO da tabela TBCLIENTE.

IV. Colunas Identity


A propriedade IDENTITY definida junto a uma coluna numérica (int, smallint, tinyint,
decimal ou numeric) torna-a auto incrementável. O sistema passa a gerar valores para a
coluna IDENTITY, para todas as linhas incluídas na tabela (portanto, não se deve
atribuir valor para ela no comando INSERT).

Importante:
· Só pode haver uma coluna IDENTITY por tabela;
· Não pode ser atualizada;
· Não permite NULL.

CREATE TABLE DBO.TBPRODUTO (IDPRODUTO INT NOT NULL IDENTITY,


DESCRPRODUTO VARCHAR(200) NOT NULL) -- DESCRIÇÃO DO PROD.

Página 12 de 39
FALS – BANCO DE DADOS 1

O exemplo acima cria uma tabela de nome TBPRODUTO. O valor para a coluna
IDPRODUTO (número interno de identificação de um produto vendido pela
companhia) é gerado automaticamente pelo sistema quando uma linha (produto) é
inserida na tabela.

O comando a seguir insere um produto na tabela TBPRODUTO.

INSERT TBPRODUTO (DESCRPRODUTO) VALUES (‘PARAFUSO FENDA


5MM’)

Observe que a coluna IDPRODUTO não foi referenciada (nem pode) no comando
INSERT. Crie esta tabela, insira linhas e visualize, com o comando SELECT, os valores
gerados pelo sistema para a coluna IDPRODUTO.

Veja outra possibilidade:

CREATE TABLE DBO.TBPRODUTO (


IDPRODUTO INT NOT NULL IDENTITY(1000,5),
DESCRPRODUTO VARCHAR(200) NOT NULL) -- DESCRIÇÃO DO PROD.

Neste exemplo, utilizamos IDENTITY(1000,5). O número 1000 (semente) será o valor


gerado para a primeira linha inserida na tabela. Para a segunda linha, o sistema gerará o
valor 1005, pois o número 5 em IDENTITY(1000,5) indica qual deve ser o incremento,
o padrão é 1.

V. Integridade de Dados
A integridade dos dados armazenados no database é conseguida definindo-se restrições:
a) Sobre o conjunto de valores válidos para as colunas de uma tabela, por exemplo,
a coluna ESTADO da tabela TBCLIENTE, do exemplo utilizado anteriormente,
de acordo com sua definição, só deve aceitar RS, SC e PR, como valores
válidos;
b) Sobre a relação entre os valores de duas ou mais colunas de uma tabela, por
exemplo, suponha a tabela ALUNO de um database de uma escola, com duas
colunas tipo data: DATA_INICIO_CURSO e DATA_FORMATURA,
obviamente, DATA_FORMATURA deve ser posterior (>=) a
DATA_INICIO_CURSO;
c) Que impeçam a duplicação indevida de linhas em tabelas;
d) Que mantenham a consistência referencial entre duas ou mais tabelas, por
exemplo, suponha um database com dados sobre os funcionários de uma
empresa e seus dependentes (esposa, filhos, etc), suponha ainda que, por
motivos que veremos a seguir, sejam criadas duas tabelas: TBFUNCIONARIO e
TBDEPENDENTE, a restrição em que “todo dependente deve estar associado a
pelo menos um funcionário” deve ser atendida, de forma a não termos linhas
“órfãs” em TBDEPENDENTE (inconsistência).

No SQL Server 7.0, os quatro tipos de restrição descritos acima podem ser
implementados através de CONSTRAINTS ou programas (TRIGGERS e STORED
PROCEDURES). Por enquanto veremos apenas as CONSTRAINTS

Página 13 de 39
FALS – BANCO DE DADOS 1

A. CHECK

Através da constraint CHECK podemos restringir o conjunto de valores válidos para


uma coluna. A seguir utilizamos CHECK para limitar os valores válidos para a coluna
ESTADO a uma das seguintes strings: RS,SC ou PR.

create table dbo.tbcliente (


CodCliente int not null,
NomeCliente varchar(50) not null,
DataCadastro datetime not null,
Estado char(2) not null check ( Estado=’RS’ or
Estado=’SC’ or
Estado=’PR’),
Telefone char(15) null,
MediaCompra money not null,
FisJur int not null
)

Se você executar o seguinte comando, obterá uma mensagem de erro, pois SP não é um
valor válido para a coluna ESTADO.

insert tbcliente
values (100,'Ana','11/20/2001','SP','1234-5678',2000.20,0)

A mensagem de erro será algo parecido com a seguinte:

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


INSERT statement conflicted with COLUMN CHECK constraint
'CK__tbcliente__Estad__45F365D3'. The conflict occurred in
database 'prof1', table 'tbcliente', column 'Estado'.
The statement has been terminated.

Obs: 'CK__tbcliente__Estad__45F365D3' é o nome gerado automaticamente pelo


sistema para a constraint check. Você pode definir um nome menos complicado
modificando o comando da seguinte forma:

create table dbo.tbcliente (


CodCliente int not null,
NomeCliente varchar(50) not null,
DataCadastro datetime not null,
Estado char(2) not null constraint EstadoCK
check (Estado=’RS’ or
Estado=’SC’
or
Estado=’PR’),
Telefone char(15) null,
MediaCompra money not null,
FisJur int not null
)

Página 14 de 39
FALS – BANCO DE DADOS 1

Exercício:
Utilize a system stored procedure SP_HELP, para obter a listagem descrevendo
a estrutura (definição) da tabela TBCLIENTE e localize na mesma a constraint
check criada e sua definição.

Outra forma de escrever a constraint check mantendo o mesmo resultado é utilizando a


cláusula IN, como segue:

create table dbo.tbcliente (


CodCliente int not null,
NomeCliente varchar(50) not null,
DataCadastro datetime not null,
Estado char(2) not null
check ( Estado in (’RS’,’SC’,’PR’) ),
Telefone char(15) null,
MediaCompra money not null,
FisJur int not null
)

Obs: Vale ressaltar que o tipo de dado selecionado para uma coluna assim como o
atributo NULL (ou NOT NULL) também impõem integridade a coluna. Campos
numéricos, por exemplo, não aceitam, obviamente, valores não numéricos, sendo,
portanto, impossível ter-se uma coluna INT com o valor 15X.34 . Em sistemas mais
antigos, era comum (não muito) encontrar datas armazenadas em campos caracteres
(CHAR), como campos caracteres aceitam tudo, datas como 31/02/2002, por exemplo,
eram encontradas. A utilização de tipos de dados apropriados para armazenamento de
datas garantem que apenas datas válidas serão aceitas. Como último exemplo, considere
o absurdo de se ter uma linha na tabela TBCLIENTE sem valor na coluna
NOMECLIENTE, caso esta coluna tivesse sido definida como não obrigatória (NULL).

Exercício:
Defina uma constraint check que restrinja a coluna FISJUR aos valores 0
(pessoa física) e 1 (pessoa jurídica), conforme definição.

B. DEFAULT

A constraint DEFAULT especifica um valor padrão a ser atribuído à coluna quando um


não for explicitamente definido no comando INSERT.

Página 15 de 39
FALS – BANCO DE DADOS 1

Introduzimos a seguir duas constraints DEFAULT para a tabela TBCLIENTE.

create table dbo.tbcliente (


CodCliente int not null,
NomeCliente varchar(50) not null,
DataCadastro datetime not null default getdate(),
Estado char(2) not null check ( Estado=’RS’ or
Estado=’SC’ or
Estado=’PR’),
Telefone char(15) null,
MediaCompra money not null default 0,
FisJur int not null
)

A constraint DEFAULT definida para a coluna DATACADASTRO especifica que se


não for explicitamente atribuída uma data a esta coluna no comando INSERT, a data do
sistema, obtida pela função GETDATE, será automaticamente atribuída a ela. Já para a
coluna MEDIACOMPRA, em condições semelhantes, é atribuído o valor 0 (zero).

Recrie a tabela, execute o INSERT abaixo e verifique o resultado.

insert tbcliente (codcliente,nomecliente,estado,fisjur)


values (1,'paulo','rs',0)

Exercício:
Modifique o comando CREATE TABLE acima definindo ‘RS’
como valor padrão para a coluna ESTADO.

C. PRIMARY KEY

Uma coluna ou combinação de colunas que identifiquem exclusivamente uma linha das
demais linhas de uma tabela é chamada de chave da tabela (Key).

Uma tabela pode ter várias chaves. Uma delas pode ser escolhida como principal
(Primary).

Exemplos de chaves:
a) O número de matrícula de um aluno da FALS identifica exclusivamente o aluno.
Ou seja, não existem dois alunos com a mesma matrícula.
b) O CPF identifica exclusivamente uma pessoa física perante a receita federal.

Para uma tabela projetada para armazenar dados sobre os alunos da FALS, por exemplo,
precisamos garantir que um mesmo número de matrícula não seja utilizado, por engano,
para dois ou mais alunos.

No SQL Server 7.0, este tipo de integridade é facilmente implementado através da


constraint PRIMARY KEY, Abaixo apresentamos um exemplo utilizando a tabela
TBCLIENTE.

Obs: Todas as colunas que compõem a PRIMARY KEY devem ter o atributo NOT
NULL.

Página 16 de 39
FALS – BANCO DE DADOS 1

create table dbo.tbcliente (


CodCliente int not null primary key,
NomeCliente varchar(50) not null,
DataCadastro datetime not null default getdate(),
Estado char(2) not null check ( Estado=’RS’ or
Estado=’SC’ or
Estado=’PR’),
Telefone char(15) null,
MediaCompra money not null default 0,
FisJur int not null
)

O comando acima define a coluna CODCLIENTE como chave primária da tabela


TBCLIENTE. Se você tentar executar o INSERT abaixo duas vezes, para a primeira vez
você obterá sucesso, mas para a segunda, uma mensagem de erro será apresentada.

insert tbcliente (codcliente,nomecliente,estado,fisjur)


values (1,'paulo','rs',0)

Mensagem de erro:
Server: Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK__tbcliente__117F9D94'. Cannot insert
duplicate key in object 'tbcliente'.
The statement has been terminated.

No exemplo abaixo, ilustramos a criação de uma chave primária composta por duas
colunas.

create table dbo.pedido(


CodCliente int not null,
DataPedido datetime not null,
CodVendedor int not null,
constraint chave_pedido primary key (CodCliente,DataPedido)
)

O sistema garantirá que não existirão duas linhas com a mesma combinação de valores
nas duas colunas, ou seja, um mesmo cliente (CODCLIENTE) pode aparecer em várias
linhas da tabela desde que em cada uma delas DATAPEDIDO seja diferente. Não será
possível, portanto, serem inseridas duas linhas com CODCLIENTE = 100 e
DATAPEDIDO=’01/01/2003’, por exemplo.

Página 17 de 39
FALS – BANCO DE DADOS 1

D. UNIQUE

Se você precisar garantir também a integridade da tabela por outras chaves além da
primária, utilize a constraint UNIQUE. A constraint UNIQUE garantirá que valores
duplicados não serão inseridos na tabela.

create table dbo.funcionario (


NumeroFuncionario int not null primary key,
NomeFuncionario varchar(100) not null,
RGFuncionario int not null unique
)

No exemplo acima, a tabela funcionário é criada com a coluna


NUMEROFUNCIONARIO como PRIMARY KEY e com a coluna
RGFUNCIONARIO (documento de identidade) como UNIQUE. De forma que, o
sistema garantirá que não existirão na tabela duas linhas com o mesmo valor na coluna
RGFUNCIONARIO. Idem para a coluna NUMEROFUNCIONARIO.

As chaves UNIQUE também podem ser compostas.

E. REVISÃO 1
O exercício a seguir visa o treinamento sobre os conceitos e comandos da linguagem
SQL (Transact-SQL) vistos até agora. O exemplo utilizado tem caráter didático, não
sendo a melhor solução a ser adotada para o cadastramento de dados sobre
eletrodomésticos. Futuramente, veremos soluções melhores.

Enunciado:
1. Crie a tabela ELETRODOMESTICOS conforme descrição abaixo, selecionando
o tipo de dado mais adequado e implemente restrições que impeçam que valores
inválidos sejam entrados.
2. Defina e implemente a chave primária para esta tabela.

Nome Coluna Descrição Valores Possíveis Obrigatório Valor


Padrão
Tipo Código numérico que 1 (=geladeia); Sim
identifica o tipo de 2 (=tanquinho) ;
eletrodoméstico 3 (=microondas);
4 (=lava roupa) ou
5 (=lava louça)
Fabricante Código numérico que 1 (=Brastemp); Sim 1
identifica o fabricante 2 (=Cônsul);
do eletrodoméstico 3 (=GE)
Modelo Texto com o modelo String de no máximo Sim
do aparelho 50 posições
Potencia Potência do aparelho Número entre 0.5 e Sim
3.7

Página 18 de 39
FALS – BANCO DE DADOS 1

Cor Cor do aparelho Uma das seguintes Sim Branca


strings: Branca, Azul e
Vermelha
NumeroSerie Número de série do Número entre Sim
aparelho 1.000.000 e 9.999.999
DataEntraEstoque Data em que o Datas entre 1/1/2003 e Sim Data do
produto entrou em 31/12/3002 sistema
estoque
Voltagem Voltagem do aparelho 110 ou 220 Sim 110
Vendido Indica se o aparelho 0 (= Não) ; (1=Sim) Sim 0
foi vendido ou não.
CodigoVendedor Código do vendedor § Número entre 1 e Não
300, se Vendido=1.
§ Ou NULL, se
Vendido=0.
DataVenda Data da venda § Igual ou posterior Não
a DataEntraEstoque.
§ NULL, se
Vendido=0.
§ NOT NULL, se
Vendido=1

F. FOREIGN KEY

Para explicarmos a constraint FOREIGN KEY utilizaremos como exemplo o exercício


da revisão 1 (acima).

Tomemos a coluna Fabricante. Uma das formas possíveis para restringirmos os valores
entrados nesta coluna (os válidos são: 1,2 ou 3) é utilizarmos uma constraint CHECK,
como a seguir:

Create Table dbo.eletrodomesticos (


….
Fabricante tinyint not null check (Fabricante in (1,2,3)) ,
….
)

O grande inconveniente é termos que alterar a estrutura da tabela sempre que passarmos
a trabalhar com produtos de outro fabricante. Neste caso, um novo código (4) referente
ao novo fabricante (Eletrolux, por exemplo) passa a ser válido para a coluna. Para tal, é
necessário alterar a constraint CHECK, excluindo-a e recriando-a através do comando
ALTER TABLE.

Exclui CHECK

ALTER TABLE ELETRODOMESTICOS


DROP CONSTRAINT nome_da_constraint_check

Página 19 de 39
FALS – BANCO DE DADOS 1

Recria CHECK

ALTER TABLE ELETRODOMESTICOS


ADD CHECK (FABRICANTE IN (1,2,3,4))

Uma alternativa melhor que dispensa a alteração na estrutura da tabela


ELETRODOMESTICOS, sempre que um novo fabricante deva ser considerado, é a
seguinte:
1) Criar uma nova tabela, de nome TBFABRICANTE, com o cadastro de cada
fabricante. Esta nova tabela teria, por exemplo, duas colunas:
§ IdFabricante – código numérico interno exclusivo de cada fabricante
(chave primária);
§ NomeFabricante – campo caracter com o nome do fabricante

Assim teríamos para a situação proposta a seguinte tabela:


IdFabricante NomeFabricante
1 Brastemp
2 Cônsul
3 GE
4 Eletrolux

2) Sempre que uma linha for inserida na tabela ELETODOMESTICOS, verificar


se o valor atribuído à coluna Fabricante é igual ao valor da coluna IdFabricante
em alguma linha da tabela TBFABRICANTE, ou seja, verificar se o valor
atribuído existe em TBFABRICANTE. Caso afirmativo, aceitar o valor.

Com esta solução, basta incluir um novo fabricante na tabela TBFABRICANTE para
que o mesmo (seu identificador – IdFabricante) passe a ser aceito como valor válido
para a coluna Fabricante da tabela ELETRODOMÉSTICOS.

Para nossa sorte, através da constraint FOREIGN KEY (chave estrangeira), o próprio
sistema executa este tipo de validação.

Para substituir a constraint CHECK pela FOREIGN KEY, podemos fazer o seguinte:

Exclui CHECK

ALTER TABLE ELETRODOMESTICOS


DROP CONSTRAINT nome_da_check_constraint

Cria FOREIGN KEY

ALTER TABLE ELETRODOMESTICOS


ADD FOREIGN KEY (FABRICANTE) REFERENCES
TBFABRICANTE(IDFABRICANTE)

Óbvio que a tabela TBFABRICANTE deve ser criada antes que o comando acima seja
executado.

Página 20 de 39
FALS – BANCO DE DADOS 1

IMPORTANTE: Para que o exemplo acima funcione, é obrigatório que a coluna


IdFabricante em TBFABRICANTE seja definida com a constraint PRIMARY KEY ou
UNIQUE.

É possível definir a FOREIGN KEY diretamente no comando CREATE TABLE, como


segue:

Create Table dbo.eletrodomesticos (


….
Fabricante tinyint not null foreign key references tbfabricante(idfabricante) ,
….
)

Obs: A chave estrangeira pode ser composta por mais de um campo.

Exercício: Crie a tabela TBFABRICANTE, insira as quatro linhas descritas,


implemente a FOREIGN KEY conforme exemplo acima e teste o seu funcionamento.

G. Habilitar e desabilitar constraints

Constraints do tipo FOREIGN KEY e CHECK podem ser desabilitadas através dos
seguintes comandos:

ALTER TABLE nome_tabela NOCHECK CONSTRAINT nome_da_constraint

Ou

ALTER TABLE nome_tabela NOCHECK CONSTRAINT ALL

Se especificado o nome da constraint, apenas ela será desabilitada. Se for utilizado


ALL, todas o serão.

Para habilitá-las, utilize os seguintes comandos:

ALTER TABLE nome_tabela CHECK CONSTRAINT nome_da_constraint

Ou

ALTER TABLE nome_tabela CHECK CONSTRAINT ALL

H. Criar constraints sem que os dados existentes na


tabela sejam verificados

Se for necessário criar uma constraint CHECK ou FOREIGN KEY em uma tabela
existente e com dados (ALTER TABLE), é padrão do sistema verificar se existe alguma
linha da tabela que viole a condição da constraint, se houver alguma, o comando é
cancelado. Em casos raros, podemos querer criar um destes tipos de constraints sem que

Página 21 de 39
FALS – BANCO DE DADOS 1

sejam verificadas as linhas já existentes, apenas as linhas incluídas ou alteradas a


posteriore serão validadas pela constraint.

Como WITH CHECK, ou seja, com verificação, é o padrão; os dois comandos a seguir
são equivalentes.

ALTER TABLE nome_tabela


ADD CONSTRAINT nome_constraint CHECK ( expressão_booleana )

ALTER TABLE nome_tabela WITH CHECK


ADD CONSTRAINT nome_constraint CHECK ( expressão_booleana )

Para que não seja feita a verificação das linhas existentes, utilizamos WITH
NOCHECK, da seguinte forma:

ALTER TABLE nome_tabela WITH NOCHECK


ADD CONSTRAINT nome_constraint CHECK ( expressão_booleana )

VI. SELECT Avançado


Já estudamos anteriormente formas simples do comando SELECT, vamos agora estudá-
lo detalhadamente.

A. Consultas com JOIN

Quando os dados a serem recuperados (lidos) de um database encontram-se em mais de


uma tabela, as mesmas devem ser combinadas em uma consulta (unidas=join) para
produzir o resultado esperado. Vamos introduzir esta operação através dos exemplos
abaixo.

Funcionarios
NumeroFunc NomeFunc
1000 Paulo
1200 Joana
1530 Jose
(Primary Key)

Dependentes
NumeroFunc NomeDep
1530 Carla
1000 Renato
1530 Carlos
1530 Mario
(Foreign Key)

Página 22 de 39
FALS – BANCO DE DADOS 1

Quando solicitada uma listagem dos funcionários e seus dependentes, no formato


abaixo, como deverá ser o comando SELECT para produzi-lo?

Resultado Desejado
Nome Funcionário Nome Dependente
Jose Carla
Jose Carlos
Jose Mario
Paulo Renato

Vamos analisar o problema em etapas.

1) SELECT *
FROM FUNCIONARIOS, DEPENDENTES

Na cláusula FROM do comando SELECT, é possível fazer referência a mais de uma


tabela, como no exemplo acima.

Ao executar o SELECT acima (1), o seguinte resultado será gerado:

NumeroFunc NomeFunc NumeroFunc NomeDep


1000 Paulo 1530 Carla
1200 Joana 1530 Carla
1530 Jose 1530 Carla
1000 Paulo 1000 Renato
1200 Joana 1000 Renato
1530 Jose 1000 Renato
1000 Paulo 1530 Carlos
1200 Joana 1530 Carlos
1530 Jose 1530 Carlos
1000 Paulo 1530 Mario
1200 Joana 1530 Mario
1530 Jose 1530 Mario

As duas primeiras colunas se referem à tabela FUNCIONARIOS, enquanto as duas


últimas, a DEPENDENTES.

Cada linha do resultado é obtida combinando 1 linha de FUNCIONARIOS com 1 linha


de DEPENDENTES, ou seja, gerando duplas (F,D), onde F é elemento de
FUNCIONARIOS e D é elemento de DEPENDENTES.
O resultado produzido é a combinação de todas as linhas de FUNCIONARIOS com
todas as linhas de DEPENDENTES (Produto Cartesiano).

Entretanto, não é o que desejamos. Precisamos eliminar do resultado as linhas em que as


2 colunas NUMEROFUNC, tenham valores diferentes. Ou, em outras palavras, manter
as linhas onde as referidas colunas tenham valores iguais. Isto pode ser feito incluindo a
cláusula WHERE no comando.

Página 23 de 39
FALS – BANCO DE DADOS 1

2) SELECT *
FROM FUNCIONARIOS, DEPENDENTES
WHERE FUNCIONARIOS.NUMEROFUNC =
DEPENDENTES.NUMEROFUNC

Note que é necessário preceder as colunas NUMEROFUNC com os nomes das tabelas a
que elas se referem. Para que a coluna NUMEROFUNC da tabela FUNCIONARIOS
não seja confundida com a coluna NUMEROFUNC da tabela DEPENDENTES.

B. USO DE APELIDO

Uma outra forma para o comando anterior que gera o mesmo resultado, mas simplifica a
escrita, utiliza um apelido para cada uma das tabelas.

3) SELECT *
FROM FUNCIONARIOS FU, DEPENDENTES DP
WHERE FU.NUMEROFUNC = DP.NUMEROFUNC

Neste comando, sempre que a tabela FUNCIONARIOS precisa ser referenciada, utiliza-
se seu apelido FU, reduzindo a escrita. Utilizamos duas letras para o apelido, mas
poderiam ser 1, 3, 5 ou mais.

C. INNER JOIN

Uma 3ª forma para o comando que também produz o mesmo resultado é a seguinte.

4) SELECT *
FROM FUNCIONARIOS FU INNER JOIN DEPENDENTES DP
ON FU.NUMEROFUNC = DP.NUMEROFUNC

Note que o critério para filtrar apenas as linhas desejadas, passa a ser especificado junto
ao ON, não mais no WHERE.

Isto não significa que a cláusula WHERE, não possa ser utilizada. No exemplo abaixo,
utilizamos WHERE para selecionar apenas as linhas cuja idade do dependente seja
superior a 10 anos (suponha que o campo IDADE, tenha sido acrescentado à tabela
DEPENDENTES),

5) SELECT *
FROM FUNCIONARIOS FU INNER JOIN DEPENDENTES DP
ON FU.NUMEROFUNC = DP.NUMEROFUNC
WHERE IDADE > 10

Note que não é preciso escrever DP.IDADE, pois não há em FUNCIONARIOS uma
coluna de nome IDADE, ou seja, não há dúvida de que IDADE, refere-se a uma coluna
de dependente. Não há ambigüidade.

Página 24 de 39
FALS – BANCO DE DADOS 1

D. LEFT JOIN
Note que nos resultados obtidos anteriormente, foram listados apenas funcionários que
possuíam pelo menos 1 dependente. Funcionários sem dependentes nunca aparecem.

Se quisermos forçar que todos os funcionários sejam apresentados pelo menos uma vez
no resultado, independentemente se eles tem ou não dependentes, precisamos reescrever
e consultar (4) substituindo INNER JOIN por LEFT JOIN, como segue:

6) SELECT *
FROM FUNCIONARIOS FU LEFT JOIN DEPENDENTES DP
ON FU.NUMEROFUNC = DP.NUMEROFUNC

O resultado gerado será o seguinte:

NumeroFunc NomeFunc NumeroFunc NomeDEP


----------- ---------- ----------- ----------
1000 Paulo 1000 Renato
1200 Joana NULL NULL
1530 Jose 1530 Carla
1530 Jose 1530 Carlos
1530 Jose 1530 Mario

(5 row(s) affected)

Para os funcionários sem dependentes, ou seja, que não atendam ao critério do JOIN
(que segue a cláusula ON), tem-se nas colunas referentes à tabela DEPENDENTES
valores NULL, como é o caso de JOANA, no exemplo.

E. RIGHT JOIN
Na consulta anterior (6) utilizamos LEFT JOIN porque a tabela FUNCIONARIOS, para
a qual queremos que todas as suas linhas sejam apresentadas ao menos uma vez no
resultado, encontra-se à esquerda do JOIN.

7) SELECT *
FROM FUNCIONARIOS FU RIGHT JOIN DEPENDENTES DP
ON FU.NUMEROFUNC = DP.NUMEROFUNC

Na consulta acima (7), invertemos a direção do JOIN, ou seja , todos os dependentes


serão apresentados no resultado, independentemente se eles possuírem ou não um
funcionário associado. Isto pode ocorrer caso não haja uma FOREION KEY, que
garanta a integridade da associação FUNCIONARIOS x DEPENDENTES. Note que,
neste caso, DEPENDENTES, tabela para a qual queremos que todas as suas linhas
sejam apresentadas ao menos uma vez no resultado, está à direita (RIGHT) do JOIN.

Note que a consulta abaixo produz exatamente o mesmo resultado consulta (6), a menos
da ordem das colunas.

8) SELECT *
FROM DEPENDENTES DP RIGHT JOIN FUNCIONARIOS FU
ON FU.NUMEROFUNC = DP.NUMEROFUNC

Página 25 de 39
FALS – BANCO DE DADOS 1

NumeroFunc NomeDEP NumeroFunc NomeFunc


----------- ---------- ----------- ----------
1000 Renato 1000 Paulo
NULL NULL 1200 Joana
1530 Carla 1530 Jose
1530 Carlos 1530 Jose
1530 Mario 1530 Jose

(5 row(s) affected)

LEFT JOIN (ou RIGHT JOIN) podem ser utilizados para solucionar a seguinte questão:
“Quais são os funcionários que não possuem dependentes?”. No exemplo, JOANA.

9) SELECT *
FROM FUNCIONARIOS FU LEFT JOIN DEPENDENTES DP
ON FU.NUMEROFUNC = DP.NUMEROFUNC
WHERE DP.NUMEROFUNC IS NULL

Para tanto, basta utilizar o fato de que, utilizando LEFT JOIN como acima, todo
funcionário sem dependente aparece 1 vez no resultado e tem valores NULL em todas
as colunas referentes à tabela DEPENDENTES. Utilizando a cláusula WHERE
selecionamos (filtramos) apenas as linhas de interesse.

NumeroFunc NomeFunc NumeroFunc NomeDEP


----------- ---------- ----------- ----------
1200 Joana NULL NULL

(1 row(s) affected)

F. JOIN DE UMA TABELA COM ELA MESMA

Em algumas situações uma tabela pode ser unida (JOIN) a ela mesma, principalmente
quando há auto-relacionamento. Por exemplo, suponha que a coluna
SUBORDINADO_A seja adicionada a tabela FUNCIONARIOS, como segue:

Funcionarios
NumeroFunc NomeFunc Subordinado_A
1000 Paulo 1530
1200 Joana NULL
1530 Jose 1200
(Primary Key)

Os valores em SUBORDINADO_A significam que Paulo é diretamente subordinado a


José (ou José é chefe de Paulo), enquanto José é diretamente subordinado a Joana (ou
Joana é a chefe de José), ou ainda, Joana é presidente da companhia, pois ela não é
subordinada a ninguém.

Página 26 de 39
FALS – BANCO DE DADOS 1

Suponha que seja solicitado o relatório: “Liste os chefes e seus subordinados diretos”,
como segue.

CHEFE SUBORDINADO
Joana José
José Paulo

A seguinte consulta pode ser utilizada para produzi-lo.

10) SELECT CHE.NOMEFUNC AS CHEFE,


SUB.NOMEFUNC AS SUBORDINADO
FROM FUNCIONARIOS CHE INNER JOIN FUNCIONARIOS SUB
ON CHE.NUMEROFUNC = SUB.SUBORDINADO_A

G. SUBQUERY

É possível na linguagem SQL construir comandos SELECT que tenham em seu corpo
outros SELECTs aninhados. Os SELECTs internos são denominados SUBQUERYs.

11) SELECT *
FROM FUNCIONARIOS
WHERE NUMEROFUNC NOT IN
(SELECT NUMEROFUNC FROM DEPENDENTES)

No exemplo acima, o texto em negrito constitui a subquery. As linhas de


FUNCIONARIOS que satisfizerem a condição da cláusula WHERE constituirão o
resultado. Ou seja, as linhas de FUNCIONARIOS onde o valor na coluna
NUMEROFUNC não (NOT) pertencer à lista gerada pela subquery.

Note que a subquery gera como resultado, se executada isoladamente, todos os valores
da coluna NUMEROFUNC de DEPENDENTES.

NUMEROFUNC
-----------
1530
1000
1530
1530

(4 row(s) affected)

A consulta (11) é, portanto, equivalente a:

12) SELECT *
FROM FUNCIONARIOS
WHERE NUMEROFUNC NOT IN (1530,1000,1530,1530)

Resumindo, a consulta (11) também lista todos os funcionários que não possuem
dependentes, ou seja, NUMEROFUNC não pertence (NOT IN) à lista
(1530,1000,1530,1530), gerada a partir da tabela DEPENDENTES.

Página 27 de 39
FALS – BANCO DE DADOS 1

H. EXISTS

Outro exemplo de subquery é a que utiliza a palavra EXISTS. Vejamos seu


comportamento através do exemplo FUNCIONARIOS x DEPENDENTES.

13) SELECT *
FROM FUNCIONARIOS FU
WHERE NOT EXISTS
(SELECT * FROM DEPENDENT ES DP
WHERE FU. NUMEROFUNC=DP. NUMEROFUNC)

Aqui novamente produzimos uma listagem com os funcionários sem dependentes. A


expressão da cláusula WHERE é verdadeira (TRUE) quando a subquery não produz
linhas (atenção para a palavra NOT), ou seja, quando não existem (NOT EXISTS)
dependentes para um dado funcionário.

Funcionarios
NumeroFunc NomeFunc
1000 Paulo
1200 Joana
1530 Jose
(Primary Key)

O processamento desta consulta ocorre da seguinte forma:


a) Toma-se uma linha de FUNCIONARIOS, por exemplo, a primeira.
b) Substitui-se na subquery FU.NUMEROFUNC por 1000 (valor de
NUMEROFUNC da 1 a linha de FUNCIONARIOS)
c) Execute a subquery resultante
(SELECT * FROM DEPENDENT ES DP
WHERE 1000=DP. NUMEROFUNC)
d) Se alguma linha for gerada significa que existe dependente para o funcionário
1000 (Paulo). Logo a expressão da cláusula WHERE será falsa.
e) Repetir o mesmo teste para todas as linhas de FUNCIONARIOS.

Página 28 de 39
FALS – BANCO DE DADOS 1

VII. GERAR INFORMAÇÕES SUMARIZADAS


Funções que calculam médias e totais são chamadas de FUNÇÕES DE AGREGAÇÃO.
Com elas em comandos SELECT é possível gerar valores sumarizados para as colunas
de tabelas. Por exemplo, calcular a média aritmética das idades dos dependentes
(armazenados na tabela DEPENDENTES). No Sql Server 7.0, as funções de agregação
são as seguintes.

Função de Agregação Descrição


AVG Média aritmética dos valores em uma expressão numérica
COUNT Número de valores em uma expressão numérica
COUNT(*) Número de linhas selecionadas
MAX Maior valor em uma expressão
MIN Menor valor em uma expressão
SUM Valor total em uma expressão numérica
STDEV Desvio padrão para todos os valores
STDEVP Desvio padrão para uma população
VAR Variância para todos os valores
VARP Variância para uma população

A. EXEMPLOS

a) Conta quantas linhas existem na tabela FUNCIONARIOS

SELECT COUNT(*) FROM FUNCIONARIOS

b) Calcula a média das idades dos dependentes

SELECT AVG(IDADE) FROM DEPENDENTES

c) Supondo uma tabela com todas as vendas realizadas pela empresa (abaixo),
calcular o valor total em reais vendido no mês de janeiro/2003.

SELECT SUM(VALOR_VENDA) FROM VENDAS


WHERE DATEPART(MONTH,MES)=1 AND
DATEPART(YEAR,MES)=2003

Página 29 de 39
FALS – BANCO DE DADOS 1

VENDAS
NumeroPedido Codigo_Vendedor Mes Valor_Venda
1001 20 01/2003 100
1002 10 02/2003 200
1003 10 12/2002 300
1004 10 02/2003 400
1005 20 12/2002 500
1006 20 01/2003 600
1007 10 01/2003 700
1008 20 12/2002 800

Obs: A coluna MES é do tipo SMALLDATETIME. Para armazenamento de mês/ano,


convencionamos utilizar sempre o valor 01 para o dia. Utilizamos a função
DATEPART que retorna parte de uma data. Por exemplo, seja a data D = 17/02/2003,
DATEPART(MONTH,D) = 2 (fevereiro), DATEPART(YEAR,D) = 2003 (ano).

IMPORTANTE: As funções de agregação, com a exceção de count(*), não levam em


consideração valores NULL nas colunas em que são aplicadas. Por exemplo, se uma
tabela tem 10 linhas e 2 colunas A e B, se em 3 linhas o valor da coluna B for NULL,
então COUNT(B) gera o valor 7. Já COUNT(*) gera 10.

B. GROUP BY

Podemos melhorar o exemplo (C) acima (total vendas) para gerar o total de vendas em
todos os meses. Para isto utilizamos a cláusula GROUP BY, como segue.

SELECT MES , COUNT(*) AS NUMERO_VENDAS,


SUM(VALOR_VENDA) AS TOTAL_VENDAS_MES
FROM VENDAS
GROUP BY MES

A cláusula GROUP BY acima especifica que as linhas da tabela VENDAS devem ser
agrupadas pela coluna MES. Ou seja, todas as linhas com o mesmo valor em MES
pertencerão ao mesmo grupo.

Grupo 01/2003
NumeroPedido Codigo_Vendedor Mes Valor_Venda
1001 20 01/2003 100
1006 20 01/2003 600
1007 10 01/2003 700

Grupo 02/2003
NumeroPedido Codigo_Vendedor Mes Valor_Venda
1002 10 02/2003 200
1004 10 02/2003 400

Página 30 de 39
FALS – BANCO DE DADOS 1

Grupo 12/2002
NumeroPedido Codigo_Vendedor Mes Valor_Venda
1003 10 12/2002 300
1005 20 12/2002 500
1008 20 12/2002 800

Para cada grupo o comando SELECT gerará uma única linha, da seguinte forma:
§ A coluna MES terá o valor do mês a que se refere o grupo;
§ A coluna NUMERO_VENDAS terá o número de linha do grupo (COUNT(*))
§ A coluna TOTAL_VENDAS_MES terá a soma dos valores da coluna
VALOR_VENDA das linhas do grupo.

O resultado do SELECT será o seguinte:

MES NUMERO_VENDAS TOTAL_VENDAS_MES


01/2003 3 1400
02/2003 2 600
12/2002 3 1600

Exercício:
a) Escreva consulta que produza relatório de vendas agrupado por
CODIGO_VENDEDOR;
b) Escreva consulta que produza relatório de vendas agrupado por MÊS e
CODIGO_VENDEDOR;

C. HAVING

É possível ainda filtrar as linhas do resultado produzido pelo comando SELECT com
GROUP BY através da cláusula HAVING.

SELECT MES , COUNT(*) AS NUMERO_VENDAS,


SUM(VALOR_VENDA) AS TOTAL_VENDAS_MES
FROM VENDAS
GROUP BY MES
HAVING SUM(VALOR_VENDA) > 1000

O resultado gerado seria o seguinte.

MES NUMERO_VENDAS TOTAL_VENDAS_MES


01/2003 3 1400
12/2002 3 1600

Note que a aplicação da condição da cláusula HAVING é feita após o processamento do


GROUP BY. Se você desejar filtrar linhas antes do processamento do GROUP BY,
utilize WHERE. Por exemplo, suponha a consulta a seguir, onde se deseja no resultado
apenas meses do ano de 2003.

Página 31 de 39
FALS – BANCO DE DADOS 1

SELECT MES , COUNT(*) AS NUMERO_VENDAS,


SUM(VALOR_VENDA) AS TOTAL_VENDAS_MES
FROM VENDAS
WHERE DATEPART(YEAR,MES)=2003
GROUP BY MES
HAVING SUM(VALOR_VENDA) > 1000

ETAPAS DO PROCESSAMENTO

Etapa 1 – Cláusula WHERE – vendas que não tenham sido realizadas em 2003 são
desconsideradas.
VENDAS
NumeroPedido Codigo_Vendedor Mes Valor_Venda
1001 20 01/2003 100
1002 10 02/2003 200
1004 10 02/2003 400
1006 20 01/2003 600
1007 10 01/2003 700

Etapa 2 – GROUP BY

MES NUMERO_VENDAS TOTAL_VENDAS_MES


01/2003 3 1400
02/2003 2 600

Etapa 3 – HAVING

MES NUMERO_VENDAS TOTAL_VENDAS_MES


01/2003 3 1400

D. COMPUTE e COMPUTE BY

COMPUTE e COMPUTE BY são utilizados para criação de relatórios com totais e


subtotais. Tomemos como exemplo a tabela VENDAS utilizada anteriormente. Através
da consulta abaixo, podemos gerar um relatório detalhado de todas as vendas realizadas,
com subtotais por mês e código vendedor.

Importante salientar que as colunas para as quais serão gerados subtotais devem ser
obrigatoriamente classificadas (ordenadas) através da cláusula ORDER BY.

SELECT NumeroPedido, Codigo_Vendedor, Mes, Valor_Venda


FROM VENDAS
ORDER BY MES,CODIGO_VENDEDOR
COMPUTE COUNT(MES), SUM(VALOR_VENDA) BY MES,Codigo_Vendedor --subtotal
COMPUTE COUNT(MES), SUM(VALOR_VENDA) -- total

Página 32 de 39
FALS – BANCO DE DADOS 1

RESULTADO

NumeroPedido Codigo_Vendedor Mes Valor_Venda


------------ --------------- --------------------------- ---------------------
1003 10 2002-12-01 00:00:00 300.0000

cnt
==========
1

sum
===================
300.0000

1005 20 2002-12-01 00:00:00 500.0000


1008 20 2002-12-01 00:00:00 800.0000

cnt
==========
2

sum
===================
1300.0000

1007 10 2003-01-01 00:00:00 700.0000

cnt
==========
1

sum
===================
700.0000

1001 20 2003-01-01 00:00:00 100.0000


1006 20 2003-01-01 00:00:00 600.0000

cnt
==========
2

sum
===================
700.0000

1002 10 2003-02-01 00:00:00 200.0000


1004 10 2003-02-01 00:00:00 400.0000

cnt
==========
2

sum
===================
600.0000

cnt
==========
8

Página 33 de 39
FALS – BANCO DE DADOS 1

sum
===================
3600.0000

(14 row(s) affected)

Página 34 de 39
FALS – BANCO DE DADOS 1

VIII. Manipulação Avançada de Dados

A. Projeção – Select Distinct ...

É com o comando SELECT DISTINCT que se realiza em SQL a operação de projeção


de uma tabela (ou relação) em relação a uma ou mais de suas colunas. Considere a
tabela abaixo.

FUNCIONARIOS
NumeroFunc NomeFunc DataNascimento
1000 Mariana 17/04/1987
1010 Ana 01/01/2000
1020 Maria 30/10/1964
1030 Jussara 17/04/1987

O comando:

Select DataNacimento from Funcionarios

Produz o seguinte resultado:

DataNascimento
17/04/1987
01/01/2000
30/10/1964
17/04/1987

Já com o comando:

Select distinct DataNacimento from Funcionários

Temos:

DataNascimento
17/04/1987
01/01/2000
30/10/1964

Ou seja, com DISTINCT, não há repetição da data 17/04/1987, não há duas linhas
iguais no resultado produzido. Dizemos que este resultado é a projeção da tabela (ou
relação) Funcionários na coluna DataNascimento. A projeção pode ser feita sobre mais
de uma coluna. O resultado será uma tabela (relação) composta pelas colunas projetadas
e por linhas da tabela original, sem repetição nestas colunas.

Página 35 de 39
FALS – BANCO DE DADOS 1

B. Operador LIKE

Através do operador LIKE é possível fazer comparações entre expressões String (cadeia
de caracteres) com um padrão criado por caracteres normais e caracteres curingas.

Por exemplo, se quisermos recuperar da tabela Funcionário dados de todos os


funcionários cujo nome começa com MA, poderíamos escrever a seguinte consulta:

Select * from funcionários where NomeFunc Like ‘MA%’

Aqui o caracter % é um curinga, significando qualquer String de zero ou mais


caracteres. Os dados de Mariana e Maria seriam apresentados como resultado do
comando.

Segue tabela com a descrição de todos os caracteres curingas utilizáveis como o


operador LIKE (extraída do Books on Line).

Curinga Descrição Exemplo


% Qualquer string de SELECT * FROM livros
zero ou mais WHERE titulo LIKE ‘%computer% ’.
caracteres Encontra todos os livros que tenham a
palavra ‘computer’ em qualquer parte
de seu título.
_ (underscore) Um único caracter. SELECT * FROM alunos
WHERE pnome LIKE ‘_aulo’.
Encontra todos os alunos cujo
primeiro nome tem cinco letras e
termina em ‘aulo’ (Paulo, Saulo, etc).
[] Um caracter dentro SELECT * FROM alunos
de um intervalo WHERE unome LIKE ‘[C-P]arsen’
especificado Encontra todos os alunos cujo ultimo
([a-f]) ou conjunto nome termina em ‘arsen’ e começa
([abcdef]). com C ou D ou E ou …ou P, por
exemplo: Carsen, Larsen, Karsen, etc.
[^] Um caracter fora de SELECT * FROM alunos
um intervalo WHERE unome LIKE ‘de[^l]%’.
especificado Alunos cujo último nome começa
([^a-f]) ou conjunto com ‘DE’e a terceira letra não é o ‘L’.
([^abcdef]).

Página 36 de 39
FALS – BANCO DE DADOS 1

C. SELECT … INTO

Com o comando SELECT…INTO é possível criar uma nova tabela no banco de dados
a partir de outra(s) tabela(s) existente(s).

Por exemplo:

Select NumeroFunc, NomeFunc


Into dbo.FuncAuxiliar
from Funcionarios
Where datepart(year,DataNascimento) >= 2000

O comando cria uma nova tabela de nome FuncAuxiliar, de propriedade do usuário


DBO, com duas colunas: NumeroFunc e NomeFunc. As linhas da tabela Funcionários
em que DataNascimento for posterior ou igual a 01/01/2000 são copia para a nova
tabela.

Obs: Para que este tipo de comando seja executado, é necessário que a opção 'select
into/bulkcopy' esteja ativa no bando de dados. Após a execução de um comando
SELECT...INTO não será mais possível fazer backup do log de trasações. Para ativar a
opção, execute o comando abaixo:

Execute sp_dboption nome_database, 'select into/bulkcopy', true

D. INSERT ... SELECT ...

Você pode copiar dados de uma tabela para outra utilizando o comando INSERT
conjuntamente com o comando SELECT. Exemplificaremos utilizando as tabelas
abaixo.

TAB_A
Coluna_A Coluna_B
1001 A1
2002 D2

TAB_B
Coluna_C Coluna_D Coluna_E
F3 1/1/2000 3003
G2 2/2/2000 4004
H5 3/3/1999 5005

Considerando que as columas ‘Coluna_A’ (TAB_A) e ‘Coluna_E’ (TAB_B) tenham o


mesmo domínio (ou similar), ou seja, tenham sido definidas com o mesmo tipo de dado
(ou similar que possibilite conversão). Idem para as colunas ‘Coluna_B’ (TAB_A) e
‘Coluna_C’ (TAB_B). Poderiamos inserir em TAB_A três novas linhas com os dados
provenientes de TAB_B através do seguinte comando:

Página 37 de 39
FALS – BANCO DE DADOS 1

Insert TAB_A select Coluna_E, Coluna_C from TAB_B

O SELECT poderia ter uma cláusula WHERE especificando as linhas a serem copiadas.

E. UNION
Através do operador UNION é possível combinar o resultado de duas consultas, desde
que ambas produzam seus resultados com a mesma quantidade de colunas e com os
mesmos tipos de dados (ou similar) coluna a coluna.

Por exemplo: Considere as tabelas utilizadas no exemplo do item anterior, o comando


abaixo produz o seguinte resultado.

Select Coluna_B,Coluna_A from TAB_A union all select Coluna_C, Coluna_E from TAB_B

Coluna_B Coluna_A
A1 1001
D2 2002
F3 3003
G2 4004
H5 5005

Com a palavra ALL todas as linhas são incorporadas no resultado final, incluindo
duplicadas. Se não especificada, linhas duplicadas são removidas.

F. UPDATE …FROM …

Pode-se alterar linhas de uma tabela baseando-se em valores armazenados em outra


tabela.

Update funcionarios set salario = salario * 1.1


From funcionarios f inner join dependentes d on f.NumeroFunc = d.NumeroFunc

No comando acima, apenas os funcionários com pelo menos 1 dependente terão seus
salários aumentados em 10 %. Isto se deve ao fato de que no INNER JOIN apenas as
linhas em funcionários com correspondentes em dependentes compõem o resultado do
join.

Poderíamos realizar a mesma operação utilizando subquerys, conforme abaixo:

Update funcionarios set salario = salario * 1.1


Where exists (select * from dependentes d where
funcionarios.numerofunc=d.numerofunc)

Note que apenas quando a subquery gerar alguma linha, ou seja quando existir em
Dependentes alguma linha com o valor em NumeroFunc igual ao valor em NumeroFunc
de Funcionário, é que o WHERE do UPDATE será VERDADEIRO e a linha de
Funcionário atualizada.

Página 38 de 39
FALS – BANCO DE DADOS 1

G. DELETE … FROM …

De forma análoga aos exemplos do item anterior, podemos excluir linhas de uma tabela
com base em valores de outras tabelas.

Delete funcionarios
From funcionarios f inner join dependentes d on f.NumeroFunc = d.NumeroFunc

O comando acima exclui da tabela Funcionários todos os funcionários com pelo menos
1 dependente (é só um exemplo!). Isso se não existir uma FOREIGN KEY entre
Funcionários e Dependentes. Abaixo o mesmo exemplo utilizando subquery, só que
desta vez excluindo os funcionários sem dependentes (repare no not).

Delete funcionarios
Where not exists (select * from dependentes d where
funcionarios.numerofunc=d.numerofunc)

Página 39 de 39

Potrebbero piacerti anche