Apostila SQL
Apostila SQL
Quando os Bancos de Dados Relacionais estavam sendo desenvolvidos, foram criadas linguagens
destinadas à sua manipulação. O Departamento de Pesquisas da IBM, desenvolveu a SQL como
forma de interface para o sistema de BD relacional denominado SYSTEM R, início dos anos 70. Em
1986 o American National Standard Institute (ANSI), publicou um padrão SQL. A SQL estabeleceu-se
como linguagem padrão de Banco de Dados Relacional.
SQL apresenta uma série de comandos que permitem a definição dos dados, chamada de DDL
(Data Definition Language), composta entre outros pelos comandos Create, que é destinado a
criação do Banco de Dados, das Tabelas que o compõe, além das relações existentes entre as
tabelas. Como exemplo de comandos da classe DDL temos os comandos Create, Alter e Drop.
Os comandos da série DML (Data Manipulation Language), destinados a consultas, inserções,
exclusões e alterações em um ou mais registros de uma ou mais tabelas de maneira simultânea.
Como exemplo de comandos da classe DML temos os comandos Select, Insert, Update e Delete.
Uma subclasse de comandos DML, a DCL (Data Control Language), dispõe de comandos de
controle como Grant e Revoke.
A Linguagem SQL tem como grandes virtudes sua capacidade de gerenciar índices, sem a
necessidade de controle individualizado de índice corrente, algo muito comum nas linguagens de
manipulação de dados do tipo registro a registro (dos modelos Hierárquico e Redes). Outra
característica muito importante disponível em SQL é sua capacidade de construção de visões, que
são formas de visualizarmos os dados na forma de listagens independente das tabelas e organização
lógica dos dados.
Outra característica interessante na linguagem SQL é a capacidade que dispomos de cancelar uma
série de atualizações ou de as gravarmos, depois de iniciarmos uma seqüência de atualizações. Os
comandos Commit e Rollback são responsáveis por estas facilidades.
Existem inúmeras versões de SQL. A versão original foi desenvolvida no Laboratório de Pesquisa da
IBM. Esta linguagem, originalmente chamada Sequel foi implementada como parte do projeto
System R no início dos anos 70. A linguagem evoluiu desde então, e seu nome foi mudado para SQL
(Structured Query Language).
Em 1986, o Americam National Standard Institute (ANSI) publicou um padrão SQL. A IBM publicou o
seu próprio SQL standard, o Systems Aplication Arquitecture Database Interface (SAA-SQL) em
1987.
Em 1989, tanto ANSI quanto ISO publicaram padrões substitutos (ANSI X3.135-1989 e ISO/IEC
9075:1989) que aumentaram a linguagem e acrescentaram uma capacidade opcional de integridade
referencial, permitindo que projetistas de bancos de dados pudessem criar relacionamentos entre
dados em diferentes partes do banco de dados. A versão em uso do padrão ANSI / ISSO SQL é o
padrão SQL-92 (ANSI X3.135-1992) mas algumas aplicações atuais dão suporte apenas ao padrão
SQL-89.
Desde 1993 há um trabalhos sendo desenvolvidos para atualizar o padrão de modo que este atenda
às características das últimas versões de bancos de dados relacionais lançadas no mercado. A
principal inovação da nova versão (chamada provisoriamente de SQL3) é o suporte à orientação a
objetos.
Algumas das características da linguagem SQL são:
Ø Permite trabalhar com várias tabelas;
Ø Permite utilizar o resultado de uma instrução SQL em outra instrução SQL (sub-queries);
Ø Não necessita especificar o método de acesso ao dado;
Ø É uma linguagem para vários usuários como:
Ø Administrador do sistema;
A SQL forma o produto cartesiano das relações chamadas na cláusula from, executa uma seleção da
álgebra relacional usando o predicado da cláusula where e, então, projeta o resultado para os
atributos da cláusula select. Na prática, a SQL pode converter esta expressão em uma forma
equivalente que pode ser processada mais eficientemente.
Exemplo
No esquema BANCO, encontre os nomes de todos os clientes de ‘Vitória’.
select cliente_nome
from CLIENTE
where cidade = ‘Vitória’
Encontre os nomes de todos os clientes.
select cliente_nome
from CLIENTE
Exemplo
No esquema EMPRESA, selecionar o nome e o RG dos funcionários que trabalham no departamento
número 2 na tabela EMPREGADO
select nome, rg
from EMPREGADOS
where depto = 2;
Nome RG
Fernando 20202020
Ricardo 30303030
Jorge 40404040
Nome RG Salário
Jorge 40404040 4.200,00
O operador * dentro do especificador select seleciona todos os atributos de uma tabela, enquanto
que a exclusão do especificador where faz com que todas as tuplas de uma tabela sejam
selecionadas. Desta forma, a expressão:
select *
from empregado;
A cláusula All é o default para o select ou seja: Select All indica para obter todas as tuplas. Logo,
esta cláusula não precisa ser colocado (a não ser, talvez por motivos de documentação).
A SQL inclui os conectores and, or e not; caracteres especiais: (, ), ., :, _, %<, >, <= , >= , = , <>, +,
- ,* e /; operador para comparação: between, como mostra o exemplo a seguir.
Exemplo
Selecionar todas as contas que possuam saldo entre 10000 e 20000.
Select conta_numero
From CONTA
Where saldo >= 10000 and saldo <= 20000
A SQL inclui também um operador para comparações de cadeias de caracteres, o like. Ele é usado
em conjunto com dois caracteres especiais:
Ø Por cento (%). Substitui qualquer subcadeia de caracteres.
Ø Sublinhado ( _ ). Substitui qualquer caractere.
Exemplo
Encontre os nomes de todos os clientes cujas ruas incluem a subcadeia ‘na’
Select distinct cliente_nome
From CLIENTE
Where rua like ‘%na%’
Para que o padrão possa incluir os caracteres especiais ( isto é, % , _ , etc...), a SQL permite a
especificação de um caractere de escape. O caractere de escape é usado imediatamente antes de
um caractere especial para indicar que o caractere especial deverá ser tratado como um caractere
normal. Definimos o caractere de escape para uma comparação like usando a palavra-chave
escape. Para ilustrar, considere os padrões seguintes que utilizam uma barra invertida como
caractere de escape.
Ø Like ‘ ab\%cd%’ escape ‘\’ substitui todas as cadeias começando com ‘ ab%cd’;
Ø Like ‘ ab\_cd%’ escape ‘\’ substitui todas as cadeias começando com ‘ ab_cd’.
A procura por não-substituições em vez de substituições dá-se através do operador not like.
Na expressão SQL acima, t1 e t2 são chamados “alias” (apelidos) e representam a mesma tabela a
qual estão referenciando. Um “alias” é muito importante quando há redundância nos nomes das
colunas de duas ou mais tabelas que estão envolvidas em uma expressão. Ao invés de utilizar o
“alias”, é possível utilizar o nome da tabela, mas isto pode ficar cansativo em consultas muito
complexas além do que, impossibilitaria a utilização da mesma tabela mais que uma vez em uma
expressão SQL. A palavra chave as é opcional.
Exemplo
No esquema EMPRESA, selecione selecione o nome e o RG de todos os funcionários que são
supervisores.
select e1.nome as “Nome do Supervisor”, e1.rg as “RG do Supervisor”
from empregado e1, empregado e2
where e1.rg = e2.rg_supervisor;
que gera o seguinte resultado:
Nome do Supervisor RG do Supervisor
João Luiz 10101010
Fernando 20202020
3.4 EXERCÍCIOS
Baseado no esquema EMPRESA, faça as seguintes consultas SQL.
1. Selecione todos os empregados com salário maior ou igual a 2000,00.
2. Selecione todos os empregados cujo nome começa com ‘J’.
3. Mostre todos os empregados que têm ‘Luiz’ ou ‘Luis’ no nome.
4. Mostre todos os empregados do departamento de ‘Engenharia Civil’.
5. Mostre todos os nomes dos departamentos envolvidos com o projeto ‘Motor 3’.
6. Liste o nome dos empregados envolvidos com o projeto ‘Financeiro 1’.
7. Mostre os funcionários cujo supervisor ganha entre 2000 e 2500.
Como padrão, SQL lista tuplas na ordem ascendente. Para especificar a ordem de classificação,
podemos especificar asc para ordem ascendente e desc para descendente. Podemos ordenar uma
relação por mais de um elemento. Como se segue:
Select *
From EMPRESTIMO
Order by quantia desc, agencia_cod asc
Para colocar as tuplas (linhas) em ordem é realizada uma operação de sort. Esta operação é
relativamente custosa e portanto só deve ser usada quando realmente necessário.
Exemplo
Selecione o nome de todos os funcionários que trabalham em projetos localizados em
Rio Claro.
select e1.nome, e1.rg, e1.depto
from empregado e1, empregado_projeto e2
where e1.rg = e2.rg_empregado and
e2.numero_projeto in
(select numero
from projeto
where localizacao = ‘Rio Claro’);
(select cliente_cod
from CONTA, AGENCIA
where CONTA.agencia_cod = AGENCIA.agencia_cod and
agencia_nome = ‘Princesa Isabel’)
and CLIENTE.cliente_cod in
(select cliente_cod
from EMPRESTIMO, AGENCIA
where EMPRESTIMO.agencia_cod= AGENCIA.agencia_cod and
agencia_nome = ‘Princesa Isabel’)
Exemplo
Encontre todas as agências que possuem ativos maiores que alguma agência de Vitória.
Observação: Uma vez que isto é uma comparação “maior que”, não podemos escrever a
expressão usando a construção in.
A SQL oferece o operador some (equivalente ao operador any), usado para construir a consulta
anterior. São aceitos pela linguagem: >some, <some, >=some, <=some, =some
select agencia_nome
from AGENCIA
where ativos > some
(select ativos
from AGENCIA
where agencia_cidade = ‘Vitória’)
Como o operador some, o operador all pode ser usado como: >all, <all, >=all, <=all, =all e <>all. A
construção > all corresponde a frase “maior que todos”.
A SQL possui um recurso para testar se uma subconsulta tem alguma tupla em seus resultados. A
construção exists retorna true se o argumento subconsulta está não-vazio. Podemos usar também a
expressão not exists.
Exemplo
No esquema EMPRESA, lise o nome dos gerentes que têm ao menos um dependente.
Select nome
from EMPREGADO
where exists
(select *
from DEPENDENTES
where DEPENDENTES.rg_responsavel = EMPREGADO.rg)
and exists
(select *
from DEPARTAMENTO
where DEPARTAMENTO.rg_gerente = EMPREGADO.rg)
Exemplo
Usando a construção exists, encontre todos os clientes que possuem uma conta e um empréstimo
na agência ‘Princesa Isabel’.
Select cliente_nome
from CLIENTE
where exists
(select *
from CONTA, AGENCIA
where CONTA.cliente_cod= CLIENTE.cliente_cod and
AGENCIA.agencia_cod = CONTA.agencia_cod and
agencia_nome = ‘Princesa Isabel’)
and exists
(select *
from EMPRESTIMO, AGENCIA
where EMPRESTIMO.cliente_cod= CLIENTE.cliente_cod and
AGENCIA.agencia_cod = EMPRESTIMO.agencia_cod and
agencia_nome = ‘Princesa Isabel’)
Observação: Note que nesta última consulta é importante a existência da cláusula distinct pois um
cliente pode Ter mais de uma conta em uma agência, e deverá ser contado uma
única vez.
Exemplo
Encontre o maior saldo de cada agência.
Select agencia_nome, max(saldo)
From CONTA, AGENCIA
Where CONTA.agencia_cod= AGENCIA.agencias_cod
Group by agencia_nome
Ás vezes, é útil definir uma condição que se aplique a grupos em vez de tuplas. Por exemplo,
poderíamos estar interessados apenas em agências nas quais a média dos saldos é maior que 1200.
Esta condição será aplicada a cada grupo e não à tuplas simples e é definida através da cláusula
having. Expressamos esta consulta em SQL assim:
Select agencia_nome, avg(saldo)
From CONTA, AGENCIA
Where CONTA.agencia_cod= AGENCIA.agencias_cod
Group by agencia_nome Having avg(saldo)>1200
Às vezes, desejamos tratar a relação inteira como um grupo simples. Nesses casos, não usamos a
cláusula group by.
Exemplo
Encontre a média de saldos de todas as contas.
Select avg(saldo)
From CONTA
3.8.2 Inserção
Para inserir um dado em uma relação, ou especificamos uma tupla para ser inserida escrevemos
uma consulta cujo resultado seja um conjunto de tuplas a serem inseridas. Os valores dos atributos
para tuplas inseridas precisam necessariamente ser membros do mesmo domínio do atributo.
Exemplo
Inserir uma nova conta para João (código = 1), número 9000, na agência de código=2 cujo valor
seja 1200.
insert into CONTA
values (2,9000,1,1200)
3.8.3 Atualizações
Em certas situações, podemos desejar mudar um valor em uma tupla sem mudar todos os valores na
tupla. Para isso, o comando update pode ser usado.
Suponha que esteja sendo feito o pagamento de juros, e que em todos saldos sejam acrescentados
em 5%. Escrevemos
update CONTA
set saldo = saldo * 1,05
Suponha que todas as contas com saldo superiores a 10000 recebam aumento de 6% e as demais
de 5%.
Update CONTA
set saldo = saldo * 1,06
where saldo >10000
Update CONTA
set saldo = saldo * 1,05
where saldo<=10000
A cláusula where pode conter uma série de comandos select aninhados. Considere, por exemplo,
que todas as contas de pessoas que possuem empréstimos no banco terão acréscimo de 1%.
Update CONTA
set saldo = saldo * 1,01
where cliente_cod in
(select cliente_cod
from EMPRESTIMO )
Exemplo
No esquema EMPRESA, atualize o salário de todos os empregados que trabalham no departamento
2 para R$ 3.000,00.
update empregado
set salario = 3000
where depto = 2;
Exemplo
No esquema BANCO, atualize o valor dos ativos. Os ativos são os valores dos saldos das contas da
agência.
A restrição not null indica que o atributo deve ser obrigatoriamente preenchido; se não for
especificado, então o default é que o atributo possa assumir o valor nulo.
Exemplo
Criar a tabela EMPREGADO do esquema EMPRESA, teríamos o seguinte comando:
create table EMPREGADO
(nome char (30) NOT NULL,
rg integer NOT NULL,
cic integer,
depto integer NOT NULL,
rg_supervisor integer,
salario, decimal (7,2)NOT NULL)
O comando create table inclui opções para especificar certas restrições de integridade, conforme
veremos.
Exemplo
Eliminar a tabela EMPREGADO do esquema EMPRESA, teríamos o seguinte comando:
drop table EMPREGADOS;
Observe que neste caso, a chave da tabela EMPREGADOS, (rg) é utilizada como chave estrangeira
ou como chave primária composta em diversos tabelas que devem ser devidamente corrigidas. Este
processo não é assim tão simples pois, como vemos neste caso, a exclusão da tabela EMPREGADO
implica na alteração do projeto físico de diversas tabelas. Isto acaba implicando na construção de
uma nova base de dados.
O comando alter table é usado para alterar a estrutura de uma relação existente. Permite que o
usuário faça a inclusão de novos atributos em uma tabela. A forma geral para o comando alter table
é a seguinte:
alter table <tabela> <add,drop,modify> <coluna> <tipo_coluna>;
onde add, adiciona uma coluna; drop, remove uma coluna; e modify, modifica algo em uma tabela.
No caso do comando alter table, a restrição NOT NULL não é permitida pois assim que se insere um
novo atributo na tabela, o valor para o mesmo em todas as tuplas da tabela receberão o valor NULL.
Não é permitido eliminar algum atributo de uma relação já definida. Assim caso você desejar
eliminar uma chave primária devidamente referenciada em outra tabela como chave estrangeira, ao
invés de obter a eliminação do campo, obterá apenas um erro.
onde, <expressão de consulta> é qualquer consulta SQL válida. Como exemplo, considere a visão
consistindo em nomes de agências e de clientes.
Create view TOTOS_CLIENTES as
(select agencia_nome,cliente_nome
from CLIENTE, CONTA, AGENCIA
where CLIENTE.cliente_cod = CONTA.cliente_cod and
CONTA.agencia_cod = AGENCIA.agencia_cod)
union
(select agencia_nome,cliente_nome
from CLIENTE, EMPRESTIMO, AGENCIA
where CLIENTE.cliente_cod = EMPRESTIMO.cliente_cod and
EMPRESTIMO.agencia_cod = AGENCIA.agencia_cod)
Uma vez que a SQL permite a um nome de visão aparecer em qualquer lugar em que um nome de
ralação aparece, podemos escrever:
insert into emprestimo_info
values (1,40,7)
Esta inserção é representada por uma inserção na relação EMPRESTIMO, uma vez que é a relação
a partir do qual a visão emprestimo_info foi construída. Devemos, entretanto, ter algum valor para
quantia. Este valor é um valor nulo. Assim, o insert acima resulta na inserção da tupla: (1,40,7,null)
na relação EMPRESTIMO.
Da mesma forma, poderíamos usar os comandos update, e delete.
Para apagar uma visão, usamos o comando
drop view <nomevisão>
Exemplo
Apagar a visão emprestimo_info.
drop view emprestimo_info
A cláusula check da SQL-92 permite modos poderosos de restrições de domínio. Ela pode ser usada
também no momento de criação da tabela.
Exemplo
create table dept
(deptno integer(2) not null,
dname char(12),
loc char(12),
check (dptono >= 100))
σ α (R1)= t1[k](R2)
Se este conjunto não for vazio, o comando remover é rejeitado como um erro, ou as tuplas que
se referem a t1 precisam elas mesmas ser removidas. A última solução pode levar a uma
remoção em cascata, uma vez que as tuplas precisam referir-se a tuplas que se referem a t1 e
assim por diante.
Ø Atualizar. Precisamos considerar dois casos para atualização: a atualização da relação
referenciadora (filha - R2) e atualização da relação referenciada (pai - R1).
Se a tupla t2 é atualizada na relação R2 e a atualização modifica valores para a chave
estrangeira α, então é feito um teste similar para o caso de inserção. Digamos que t2 denote o
novo valor da tupla t2’. O sistema precisa assegurar que:
σ α (R1)= t1[k](R2)
...)
Neste exemplo, se a remoção de uma tupla da tabela agência resultar na violação da regra de
integridade, o problema é resolvido removendo as tuplas associadas com esta agência da tabela
conta. De forma semelhante, se o código de uma agência for alterado, as contas desta agência serão
também alteradas.
3.11.3 Asserções
Uma asserção (afirmação) é um predicado expressando uma condição que desejamos que o banco
de dados sempre satisfaça. Quando uma assertiva é criada, o sistema testa sua validade. Se a
afirmação é válida, então qualquer modificação posterior no banco de dados será permitida apenas
quando a asserção não for violada.
Restrições de domínio e regras de integridade referencial são formas especiais de asserções.
O alto custo de testar e manter afirmações tem levado a maioria de desenvolvedores de sistemas a
omitir o suporte para afirmações gerais. A proposta geral para a linguagem SQL inclui uma
construção de proposta geral chamada instrução create assertion para a expressão de restrição de
integridade. Uma afirmação pertencente a uma única relação toma a forma:
create assertion <nome da asserção> check <predicado>
Exemplo
Definir uma restrição de integridade que não permita saldos negativos.
create assert saldo_restricao
check (not exists (select * from CONTA where saldo < 0) )
Exemplo
Só permitir a inserção de saldos maiores que quantias emprestadas para aquele cliente.
create assert saldo_restricao2
check (not exists
(select *
from conta
where saldo <
(select max(quantia)
from EMPRESTIMO
where EMPRESTIMO.cliente_cod = CONTA.cliente_cod)))
4. Consulte todas as empresas que funcionam em cidades que não moram pessoas cujo
primeiro nome seja Maria (usar operações de conjunto).
Select Empresas.NomeEmpresa
from Empresas
Where Empresas.Cidade not in
(select Cidade
from Pessoas
Where Pessoas.NomePessoa like ‘Maria%’)
5. Consulte todas as pessoas que não trabalham em Vitória e que ganham acima de 2000 em
ordem decrescente da cidade onde moram.
Select Pessoas.NomePessoa
from Pessoas, Trabalha, Empresas
where Pessoas.CodPessoa = Trabalha.CodPessoa and
Trabalha.CodEmpresa = Empresas.CodEmpresa and
Empresas.Cidade < > ‘Vitória’ and Salario > 2000
order by pessoas.cidade desc
6. Consulte todas as pessoas que não trabalham na empresa que comece com ‘inf_’ em
ordem alfabética.
Select Pessoas.NomePessoa
from Pessoas, Trabalha, Empresas
where Pessoas.CodPessoa = Trabalha.CodPessoa and
Trabalha.CodEmpresa = Empresas.CodEmpresa and
Empresas.nomeEmpresa not like ‘inf&_%’ scape ‘&’
order by nomeEmpresa
and venda.coda in
(select coda
from Automovel, Fabricante
where Automovel.codf = Fabricante.codf
and Fabricante.Nomef = ‘Ford’)
(select coda
from Automovel, Fabricante
where Automovel.codf = Fabricante.codf
and Fabricante.Nomef = ‘Volks’)
12. Selecione todos os clientes que possuem contas em agencia(s) que possui(m) o maior
ativo.
Select cliente_nome
from clientes, depositos
where clientes.cliente_cod = depositos.cliente_cod and
depositos.agencia_cod in
(select agencia_cod
from agencias
where ativos >= all
(select ativos
from agencias)
15. Selecione o valor médio de empréstimos efetuados por cada agência em ordem crescente
das cidades onde estas agências se situam.
Select agencia_nome, avg(quantia) as valor_medio
from emprestimos, agencias
where emprestimos.agencia_cod = agencias.agencia_cod
group by agencia_nome
order by cidade
16. Selecione a(s) agência(s) que possui(m) a maior média de quantia emprestada.
Select agencia_nome
from agencias, emprestimos
where emprestimos.agencia_cod = agencias.agencia_cod
group by agencia_nome
having agv(quantia) >= all
(select avg(quantia)
from emprestimos
group by agencia_cod)
19. Selecione o saldo de cada cliente, caso ele possua mais de uma conta no banco.
Select cliente_nome, sum(saldo)
from clientes, depositos
where clientes.cliente_cod = depositos.cliente_cod
group by cliente_nome
having count(agencia_cod) >1
22. Incluir na empresa de código ‘01’ todos os moradores de Vitória com um salário=100.
Insert into trabalha (codPessoa, codEmpresa, Salario)
Select codpessoa, ‘01’, 100 from pessoas where cidade = ‘Vitória’
23. Uma determinada empresa de código ‘x’ vai contratar todos os funcionários da empresa
de código ‘y’ que ganham acima de 1000, dando um aumento de salário de 10%. Faça
comando(s) SQL para que tal transação seja efetuada.
Insert into trabalha (codPessoa, codEmpresa, Salario)
Select codpessoa, ‘x’, salario*1.1
from trabalha
where codempresa=‘y’ and salario >1000
25. Fazer um comando SQL para ajustar o salário de todos os funcionários da empresa
‘Campana’ em 5%.
Update trabalha
Set salario = salario * 1.05
Where codEmpresa in
(select codEmpresa
from empresas
where nomeEmpresa = ‘Campana’)
26. Todas as pessoas que moram em Colatina e trabalham na empresa ‘Campana’ deverão
mudar para Vitória, devido aos requisitos do diretor da empresa. Faça comando(s) SQL
para fazer esta atualização da cidade.
Update Pessoas
Set cidade = ‘Vitória’
Where codPessoa in
(select codPessoa
from Pessoas, Trabalha, empresas
where Pessoas.codPessoa = Trabalha.CodPessoa and
Pessoas.cidade = ‘Colatina’ and
Trabalha.CodEmpresa = Empresas.codEmpresa and
nomeEmpresa = ‘Campana’)
AGENCIA
agencia_cidade agencia_nome agencia_cod ativos
CONTA
cliente_cod agencia_cod conta_numero saldo
EMPRESTIMO
cliente_cod, emprestimo_numero quantia agencia_cod
CLIENTE
cliente_cod cliente_nome rua cidade
Tabela EMPREGADO
Tabela DEPENDENTES
2 5 20202020 5 10
3 10 20202020 10 25
2 20 30303030 5 35
40404040 20 50
50505050 20 35