Professional Documents
Culture Documents
Œ Introdução
Todo Sistema Gerenciador de Banco de Dados (SGBD) deve oferecer aos seus usuários e administradores
meios de criar definições de dados, bem como manipular estes dados armazenados em suas bases. Cabe
ressaltar que estas linguagens têm um caráter diferenciado das linguagens de programação, de natureza
a
procedural (linguagens de 4 geração).
Para isto, cada SGBD implementa a chamada Sublinguagem de Dados (DSL), que se subdivide na
Linguagem de Definição de Dados (DDL – Data Definition Language), e a Linguagem de Manipulação de
Dados (DML – Data Manipulation Language).
A Linguagem Estruturada de Consulta (SQL – Structured Query Language) foi desenvolvida pela IBM, e
padronizada pelo comitê ANSI (American National Standardization Institute ), segundo o padrão ANSI 89. Tem
o objetivo de acessar, de forma estruturada e declarativa, (não procedural, ou seja, não é necessário que o
usuário programe qualquer algoritmo para acessar as tuplas de uma relação) instâncias de tabelas de bases
de dados. Sua principal tarefa é, portanto, criar e manter objetos, manipular e recuperar dados do banco de
dados, administrar dados e manter a segurança.
• Comentários
1. Com delimitadores: /* e */
Estas marcam delimitam o escopo de um comentário em uma consulta. Esta pode ser inclusive maior que
uma linha.
Exemplo:
/* Este é um exemplo de um comentário que aparece em uma ou mais consultas SQL. Como podemos
notar, este comentário não se restringe a apenas uma linha. */
2. Sem delimitadores: --
A marca acima indica que, a partir daquele ponto, tudo que se seguir até o final da linha representa um
comentário. Portanto, caso seja necessário comentar uma nova parte da consulta em uma linha posterior,
deve-se ou utilizar os delimitadores de início e fim de comentário explanados no item 1, ou marcar com um
novo --. Lembre-se que não se pode continuar uma consulta após a marca anterior ter sido indicada.
Exemplo:
1
SELECT nome_func -- Estamos selecionando o campo “nome_func ”
FROM Funcionário -- da tabela de funcionários
WHERE idade >= 25 -- que tenham pelo menos 25 anos de idade
Subcategoria da SQL que permite a visualização e alteração do conteúdo dos dados de tabelas básicas,
temporárias ou visões. É de valia tanto para o Administrador de Banco de Dados, porém tem seu uso mais
freqüente com os desenvolvedores de aplicação e usuários avançados.
Ä O comando SELECT
Formato Geral:
Este comando, um dos mais utilizados pelos usuários de Sistemas Gerenciadores de Banco de Dados, tem
a função principal de recuperar de dados de uma ou mais tabelas do banco de dados, possivelmente
segundo algum critério, porém não obrigatoriamente.
Além disso, o resultado da consulta pode ser classificado de diversas formas: agrupado de forma
discriminada ou não, ordenado as cendente ou descendentemente.
Podemos também utilizar as funções agregadas (pág.21) para inferir algum resultado de uma ou mais
tabelas. Seu mecanismo declarativo permite consultas em várias tabelas que se relacionam, através dos
atributos que implementam estes relacionamentos. Projeções são da mesma forma permitidas, bem como a
declaração de subconsultas.
Para detalhar com maior acurácia todo o poder desta instrução, detalhemos primeiramente o significado de
cada uma de suas cláusulas, seguindo com exemplos de consultas que possuem diferentes características.
Exploraremos, nestas consultas, o uso de predicados, a junção entre tabelas (aliás, o aspecto mais
importante nos sistemas relacionais), o agrupamento e as consultas baseadas no resultado de outras
consultas.
Nos exemplos a seguir, considere as tabelas -exemplo anteriores com as seguintes instâncias:
2
FUNCIONÁRIO
DIVISÃO
DEPARTAMENTO
3
As consultas a seguir terão os as tabelas abaixo como resultados (classificação segundo Date [1]):
4
/* Mostre o número da matrícula, o nome, o endereço e o salário de todos os funcionários que possuam
matrícula menor que 11000 */
matricula nome_func
11344 Jorge de Abreu Soares
11345 Marcelo Vasconcelos
11057 Roberto Fernandes Gomes
matricula nome_func
11057 Roberto Fernandes Gomes
11345 Marcelo Vasconcelos
11344 Jorge de Abreu Soares
Obs.: Poderíamos ter especificado a coluna de ordenação pelo seu número (SELECT ... ORDER BY 2 DESC)
5
(h) Consulta de junção com igualdade simples:
cod_dep nome_depto
cod_dep nome_depto
/* Mostre em pares o número de matrícula do funcionário que receba um salário maior que outro funcionário, se
ambos trabalharem na divisão de código 7321 */
O_que_ganha_mais O_que_ganha_menos
10223 11344
11057 11344
11057 10223
6
(k) Consulta de junção de três tabelas:
SELECT Funcionário.*
FROM Departamento, Divisao, Funcionário
WHERE (cod_lotacao = cod_divisao)
AND (depto = cod_dep OR cod_lotacao = cod_dep)
AND sig_depto = ‘INF’
ORDER BY matricula
/* Mostre todos os dados do funcionário que trabalhem na departamento de nome ‘INF’, ou em uma divisão
cuja departamento responsável tenha nome ‘INF’ */
A cláusula UNION
Efetua a união lógica do resultado de duas consultas.
Formato Geral:
O resultado das consultas 1 e 2 devem ser compatíveis, ou seja, os atributos retornados pelas consultas
devem ser os mesmos.
Exemplo:
7
matricula nome_func endereco
10223 Carlos Henrique Oliveira Av. Marques de Sapucaí,40
10377 Adelci Moura Lima Av. Rio Branco, 09
10902 Alberto Mello de Cima Av. Marques de Sapucaí,40
11057 Roberto Fernandes Gomes Av. Barão de Ladário, 50
11344 Jorge de Abreu Soares R. Uruguaiana, 50
11345 Marcelo Vasconcelos NULL
A cláusula GROUP BY
Este operador organiza a tabela em grupos que possuam o mesmo valor de atributo. Esta organização é lógica,
e não se dá no nível físico do banco de dados.
Por exemplo, imagine que queremos saber o número de funcionários alocados por divisão. Para isso, nossa
consulta deverá trabalhar em cima de grupos, e a partir destes grupos procederemos os devidos cálculos.
No exemplo citado, a consulta SQL teria a seguinte forma:
e resultaria:
cod_lotacao total_funcionarios
7105 1
7300 1
7321 4
7322 2
7323 2
Se quiséssemos melhorar o as pecto da consulta anterior, imprimindo não só o código mas também o nome
da divisão ou da departamento, teríamos de realizar uma junção com a tabela de divisões e a de
departamentos, e teríamos a seguinte consulta:
8
/* Mostre o código, o nome, o nome estendido e o total de funcionários de todas as divisões, agrupando
pelo código das divisões */
e o resultado a seguir:
Observação:
A cláusula AS, especificada na consulta acima, serve para entitular uma coluna de um resultado de
consulta. Quando recuperamos, através da cláusula FROM, um atributo, seu nome vem encabeçando os
resultados. Contudo, quando usamos funções agregadas, por exemplo, o interpretador de consultas não
tem um nome padrão com significado a atribuir (o padrão é o número da coluna; no caso acima, ao invés
de total_funcionarios, teríamos col3). Quando se utiliza a cláusula FROM, o rótulo passado é utilizado.
Esta cláusula não permite o uso de strings. Exemplo: ‘total funcionarios’ não pode substituir
total_funcionarios.
A cláusula HAVING
A cláusula WHERE no comando SELECT serve, na maioria dos casos, para impor uma determinada
restrição sobre linhas de uma tabela, seja ela uma tabela básica ou derivada de junções. Por exemplo,
quando o interpretador analisa a consulta:
SELECT *
FROM Funcionário
WHERE matricula > 10500
a tabela de funcionários tem o atributo matricula de todas as tuplas analisado, e somente os que atendem à
condição especificada (no caso, matricula > 10500) são devolvidas.
Com a cláusula HAVING acontece um processamento equivalente. Porém, a semântica se aplica à consultas
que possuam a cláusula GROUP BY. Logo, toda vez que queremos especificar a cláusula HAVING, deve-se
ter um GROUP BY associado.
9
A cláusula HAVING, na verdade, impõe uma determinada restrição (ou grupo de restrições) à grupos de uma
tabela, que representa o resultado de um processamento. Analisemos um exemplo semelhante ao anterior:
Se tivéssemos imposto uma restrição aos grupos, através da cláusula HAVING, a consulta seria:
Predicados
1. O predicado LIKE
Usado quando quer-se selecionar strings quaisquer que obedeçam a um certo padrão. O “caracter-coringa”
‘_‘ é usado para substituir 1 caracter, e ‘%’ uma substring.
10
Formato Geral:
onde expressão pode ser um atributo ou uma expressão contendo funções de string. O padrão deve
obrigatoriamente ser uma string.
Exemplo:
Se, em uma tabela, temos as strings ‘ABC DE‘,‘A SDFGF‘, e ‘DRF DA‘, e especificamos como argumento
de uma consulta a string ‘___ __‘, a primeira e a terceira strings serão devolvidas como resultado da
consulta. Já se especificarmos um predicado LIKE com uma string ‘A%’, a consulta retornará as strings
‘ABC DE‘ e ‘A SDFGF‘.
A consulta:
SELECT *
FROM Funcionário
WHERE nome_func LIKE ‘C__los %’
OR nome_func LIKE ‘%lores’
/* Mostre todos os dados dos funcionários que tenham nome terminando começando com ‘C’, seguido
de dois caracteres quaisquer e do padrão ‘los ’. Os demais caracteres do nome, depois destas
verificações, não mais importam */
Se a cláusula ESCAPE for espec ificada, o processador de consultas não tratará o caracter especificado
nesta cláusula com um tratamento comum. Vejamos como seria analisada uma consulta utilizando esta
cláusula:
/* Mostre todos os dados dos funcionários que tenham nome terminando com o padrão ‘Aima’, ‘Bima’,
‘Cima’, ‘Dima’, ‘Eima’ ou ‘Fima’ */
Na consulta acima, os colchetes têm a função específica de indicar uma faixa de caracteres (entre os
colchetes). O interpretador de consultas irá procurar no atributo nome_func das tuplas de funcionário
strings de qualquer tamanho, que necessariamente terminem com ‘IMA’. Contudo, o quarto caracter, a
11
partir do último, pode ser qualquer um dentro da faixa A-F, ou seja, os caracteres ‘A’, ’B’, ‘C’, ‘D’, ‘E’ e ‘F’.
Se alguma tupla tiver um nome que termine em ‘AIMA’, ‘BIMA’, ‘CIMA’, ‘DIMA’, ‘EIMA’ ou ‘FIMA’ satisfazem
à consulta.
Já a consulta:
/* Mostre todos os dados dos funcionários que tenham nome terminando com o padrão ‘[A-F]ima’ */
retornaria como resultado a consulta vazia, pois procurar-se-ia strings no atributo nome_func das tuplas
que terminassem em ‘[A-F]ima’.
2. O predicado BETWEEN
Verifica se o valor de um determinado atributo ou expressão pertence a um intervalo, limitado por dois outros
atributos ou expressões.
Formato Geral:
y [NOT] BETWEEN x AND z
Exemplos:
/* Mostre todos os dados dos funcionários que tenham número de matrícula entre 10500 e 11000 */
e o resultado da consulta:
/* Mostre todos os dados dos funcionários que não tenham número de matrícula entre 10500 e 11000 */
12
matricula nome_func endereco salario cod_lotacao
10223 Carlos Henrique Oliveira Av. Marques de Sapucaí,40 14.875,22 7321
10258 Marcelo Faria Espíndola Alameda Final, 1000 79.500,00 7322
10377 Adelci Moura Lima Av. Rio Branco, 09 63.000,00 7105
10490 Renato Braga Gadelha R. das Acácias, 60 80.000,00 7300
11057 Roberto Fernandes Gomes Av. Barão de Ladário, 50 45.500,00 7321
11344 Jorge de Abreu Soares R. Uruguaiana, 50 500,00 7321
11345 Marcelo Vasconcelos NULL NULL 7321
Observação:
3. O predicado IS NULL
Formato Geral:
Esta sentença é verdadeira se o valor retornado por expressão for nulo (ou não for nulo, quando NOT é
especificado).
Exemplos:
e a consulta:
SELECT * FROM Funcionário
WHERE endereco IS NOT NULL
/* Mostre todos os dados dos funcionários que não tenham um endereço nulo */
retorna:
13
matricula nome_func Endereco salario cod_lotacao
10223 Carlos Henrique Oliveira Av. Marques de Sapucaí,40 14.875,22 7321
10258 Marcelo Faria Espíndola Alameda Final, 1000 79.500,00 732 2
10377 Adelci Moura Lima Av. Rio Branco, 09 63.000,00 7105
10490 Renato Braga Gadelha R. das Acácias, 60 80.000,00 7300
10713 Aldenir Machado Flores Tr. Mário Filho, 60 78.000,00 7323
10902 Alberto Mello de Cima Av. Marques de Sapucaí,40 8.574,45 7323
10922 Leonardo Sartori Filho R. Miguel Couto, 23 25.880,01 7322
11057 Roberto Fernandes Gomes Av. Barão de Ladário, 50 45.500,00 7321
11344 Jorge de Abreu Soares R. Uruguaiana, 50 500,00 7321
4. O predicado IN
O resultado da expressão que contém este predicado será verdadeiro se e somente se o valor do operando
(chamemos nos nossos exemplos de x) aparecer na lista de valores ou na subconsulta subsequente.
Formato Geral:
x [NOT] IN (lista_de_valores | subconsulta)
onde:
lista_de_valores = valor [ , valor ]
Exemplos:
SELECT * FROM Funcionário
WHERE matricula IN (10078, 11404, 11057)
/* Mostre todos os dados dos funcionários que tenham matrícula igual a 10078, 11404 ou 11057 */
retorna:
cod_divisao nome_divisao
7321 Divisão de Desenvolvimento de Aplicações
14
5. O predicado EXISTS
Formato Geral:
A sentença acima é verdadeira se e somente se o conjunto retornado pela subconsulta não for vazio. No
caso de a palavra reservada NOT ser explicitada, o sentido se inverte: a sentença é verdadeira se o conjunto
retornado pela subconsulta for vazio.
Exemplos:
SELECT nome_depto
FROM Departamento
WHERE NOT EXISTS (SELECT *
FROM Divisao
WHERE sig_divisao = ‘DIMED’)
/* Exiba todos os dados das departamentos, se por acaso não existir alguma divisão de nome ‘DIMED’ */
não exibe nenhum resultado, já que a subconsulta retorna uma tupla, e a consulta principal executaria a
seleção no caso de nenhuma tupla ser encontrada.
Já a consulta:
exibiria:
Observação:
• A cláusula EXISTS, neste caso, funciona como um sinalizador da execução da consulta; ou seja, a
consulta mais externa só seria executada no caso de haver alguma divisão na tabela de divisões cujo
nome fosse “DIMED”
6. O predicado ANY-OR-ALL
Formato Geral:
operador-any-or-all (subconsulta)
15
A sentença acima é verdadeira se e somente se pelo menos um dos valores retornados pela subconsulta for
idêntico ao valor sendo comparado, no caso do operador ANY. Já com o operador ALL, a sentença é
verdadeira se o valor comparado for igual a todos os valores retornados pela subconsulta.
<> ANY (ou != ANY) <> SOME (ou != SOME) <> ALL(ou != ALL )
Exemplos:
SELECT cod_divisao, nome_divisao
FROM Divisao
WHERE mat_diretor = ANY ( SELECT matricula
FROM Funcionário
WHERE sig_divisao = ‘DIDAP’)
/* Mostre o código e o nome estendido das divisões cujo nome seja ‘DIDAP’ */
retorna:
cod_divisao nome_divisao
7321 Divisão de Desenvolvimento de Aplicações
/* Mostre todos os dados dos funcionários com número de matrícula menor que 10500 */
devolve:
16
Ä O comando INSERT
ou
INSERT INTO tabela [ ( nome-do atributo [ , nome-do atributo ] ) ]
sub-consulta
Comando que insere ou um registro completo, ou alguns atributos de um registro, deixando os demais com
valor nulo.
Exemplos:
2. Já a sentença
insere o registro acima na tabela de Funcionários, com o campo “endereco” desconhecido (nulo).
3. As sentenças
armazena na tabela “Temporária “, o nome de cada departamento e o número de diretores das suas
divisões subordinadas..
Ä O comando DELETE
Formato Geral:
17
Este comando remove todas as tuplas de uma tabela, segundo a especificação da cláusula WHERE, caso
exista. Se esta não existir, todas as instâncias da tabela são removidas; contudo, a descrição da tabela no
catálogo do sistema permanece intacta, por só poder ser alterada pelos comandos da linguagem de
definição de dados.
Exemplos:
1. A sentença
2. Já a sentença
Ä O comando UPDATE
Formato Geral:
UPDATE tabela
SET atributo = expressão [ , atributo = expressão ]
[WHERE condição ]
Modifica o(s) valor(es) de atributo(s) de uma tabela, seguindo ou não uma determinada condição.
Exemplos:
UPDATE Funcionário
SET endereco = ‘Rua Mena Barreto, 20’
WHERE nome_func = ‘Jorge de Abreu Soares’
/* Modifique os endereços das tuplas cujo nome de funcionário é “Jorge de Abreu Soares” */
Funções Agregadas
Retornam um único valor de acordo com o conteúdo de uma coluna. São amplamente utilizadas, já que têm a
característica importante de inferir resultados a partir de dados resultantes de consultas.
Formato Geral:
18
onde nome -da-função pode assumir os seguintes valores:
max O mesmo do argumento Ocorrência de valor máximo dentre todas em uma coluna
min O mesmo do argumento Ocorrência de valor mínimo dentre todas em uma coluna
Observações:
• A palavra reservada DISTINCT elimina ocorrências duplicadas do argumento, e não pode ser usada em
conjunto com as funções “max“ e “min“.
• Valores nulos são ignorados por funções agregadas, exceto a função “count “.
• Aceita o caracter “*” como máscara, tendo a função de determinar não mais o número de ocorrências de
uma coluna, mas sim das linhas de uma tabela
• Valores nulos serão computados caso se use esta função com o caracter “*”
Exemplos:
Baseando-se ainda na tabela e nas instâncias da tabela de Funcionários:
19
SELECT max(Funcionário.salario) FROM Funcionário 80.000,00
/* Mostre o valor máximo de salário percebido por um funcionário */
SELECT min(Funcionário.matricula) FROM Funcionário 10223
/* Mostre a menor matrícula de funcionário */
a o
Note que, na 3 consulta, o 6 registro da tabela de Funcionários possui alguns valores nulos de atributos.
Como a função count não consegue diferenciar este tipo de valor quando conta linhas, o resultado final inclui
este 6o registro.
Vimos anteriormente que a maioria dos Sistemas Gerenciadores de Bancos de Dados possuem algum tipo
abstrato que implemente representação de datas. Vejamos então alguns exemplos do uso deste tipo no
sistema CA -OpenIngres:
• SELECT *
FROM Funcionário
WHERE interval (‘year’, date(‘today’) – date(dat_nascim)) > 50
/* Mostre todos os dados dos funcionários maiores de 50 anos */
Separadores de Sentenças
• Sempre ao final de cada instrução SQL que atualize dados, é boa prática executar a instrução commit,
de forma que se garanta que os dados modificados sejam realmente gravados na base de dados
Nomes Correlatos
Servem para renomear temporariamente uma tabela em uma consulta, seja para abreviar nomes de tabelas
longos, como para propiciar a junção de uma tabela com ela mesma.
Exemplo:
SELECT func.nome_func
FROM Funcionário func
Observações:
20
• Nomes correlatos devem ser únicos, ou seja, não se pode especificar um nome correlatos para duas
tabelas diferentes.
Exemplo:
SELECT tab.nome_func
FROM Funcionário tab, Cidade tab-- “tab” foi especificado para duas tabelas distintas
• Se for especificado um nome correlativo para uma tabela, só se deve utilizar este nome na consulta, e
não mais o nome real da tabela
Exemplo:
SELECT func.nome_func
FROM Funcionário func -- Consulta correta
e não
SELECT Funcionário.nome_func
FROM Funcionário func -- Consulta errada
• Não se pode usar nomes de tabelas existentes como correlatas para outras tabelas.
Exemplo:
SELECT func.nome_func
FROM Func ionário Func, Cidade Localidade
WHERE Localidade.nom_locali = ‘Rio de Janeiro’
• O interpretador não procura por atributos de tabelas não correlatas entre sub-consultas do mesmo nível
Exemplo:
/* Mostre o nome dos funcionários e o código de sua lotação que trabalhem nas divisões da
departamento de nome ‘INF’, ou cujo nome do funcionário seja ‘José da Silva’ */
O atributo func da sentença func = ‘José da Silva’ será buscado primeiramente na tabela Divisão da
cláusula FROM. Como não será encontrado, a análise continua na cláusula FROM imediatamente
acima (... FROM Funcionário, Divisão ...). Em hipótese alguma este atributo seria buscado na
cláusula ... FROM Divisão, Departamento ... da primeira subconsulta.
21
• Em consultas aninhadas, quando não se qualificam as tabelas com nomes correlatos, o interpretador de
consultas irá resolvê-las a partir da cláusula FROM mais próxima para a mais externa.
Exemplo:
SELECT nome_func
FROM Funcionário
WHERE salario > ( SELECT avg(salario)
FROM Divisão
WHERE (cod_lotacao = cod_divisao)
AND (sig_divisao = ‘DIDAP’)
AND (matricula > 200) )
/* Mostre o nome dos funcionários que trabalhem na divisão de nome ‘DIDAP’, que tenham matricula
maior que 200, e que recebam acima da média da divisão */
Esta é a subcategoria de SQL que permite alteração de dados no catálogo do sistema. Normalmente, é de
uso exclusivo do Administrador de Banco de Dados; contudo, seu uso fica sujeito à política da empresa.
• CREATE [TABLE | VIEW | INDEX] – Criação de uma tabela (C REATE TABLE), de uma visão
(CREATE VIEW ) ou de um índice (CREATE INDEX).
• ALTER TABLE – Alteração da definição (meta-esquema) de uma tabela, com a adição de uma coluna à
esquerda.
• DROP [TABLE | VIEW | INDEX] – Destruição (dados e definição) de uma tabela básica (D ROP
TABLE), de uma visão (DROP VIEW) ou de um índice (DROP INDEX).
Observações:
• Considere os itens envoltos em colchetes como opcionais.
22
Ä O comando CREATE TABLE
Formato Geral:
cria a tabela
FUNCIONÁRIO(matricula, nome_func, endereco, salario, cod_lotacao);
e a obrigatoriedade de valores não nulos nos campos matricula e cod_lotacao.
Formato Geral:
Exemplo:
/* Crie a visão “Funcionários_Informatica”, com o número da matrícula e o nome dos funcionários que
trabalhem na divisão de nome ‘DIDAP’ */
Formato Geral:
23
onde ordem pode assumir os valores ASC (ascendente – valor padrão) ou DESC (descendente) para o
armazenamento do índice para um certo atributo.
A cláusula CLUSTER especifica um índice agrupado (o armazenamento físico dos registros no disco
levará em conta a relação entre eles, ou seja, se a tupla t1 se relaciona com a tupla r2, então o sistema
procurará armazená-las de forma que o tempo de transferência de dados do disco magnético para a
memória seja o menor possível). Cabe salientar que uma tabela básica só pode ter um índice utilizando a
cláusula CLUSTER em um dado momento.
A cláusula UNIQUE faz com que duas tuplas da tabela não tenham o mesmo valor de campo indexado em
um dado momento.
Exemplo:
Formato Geral:
Exemplo: A sentença
Formato Geral:
Esta sentença não só remove a descrição da tabela do catálogo do banco, como todas suas instâncias,
visões e índices definidos sobre ela.
24
Ä O comando DROP INDEX
Formato Geral:
Formato Geral:
Remoção da visão especificada, bem como todas as visões definidas a partir da especificada.
Exemplo:
Ä O comando COMMENT
Formatos Gerais:
Exemplos:
/* Adicione a string ‘Nome completo do Funcionário’ como comentário à coluna “nome_func” da tabela
“Funcionário” */
Referências Bibliográficas
[2] CA-OpenIngres SQL Reference Guide 1.1; Computer Associates, Junho 1995
[3] CA-OpenIngres Open SQL Reference Guide 1.1; Computer Associates, Junho 1995
25