Apostila

Transcrição

Apostila
T301B
SQL
Structure Query Language
Luis Fernando Calábria
Erick Franklin
Leonardo Bandeira
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Sumário
1.
2.
INTRODUÇÃO
3
1.1.
1.2.
1.3.
1.4.
1.5.
3
3
4
4
5
A LINGUAGEM SQL
6
2.1.
2.2.
2.3.
6
7
7
7
7
8
8
2.4.
3.
5.
6.
7.
CRIANDO UMA TABELA
IDENTIFICADORES E ATRIBUTOS
TIPOS DE DADOS
2.3.1.
DADOS CARACTERES “STRINGS”
2.3.2.
DADOS NUMÉRICOS
2.3.3.
DADOS DATA E HORA
INCLUINDO DADOS
QUERIES: OBTENDO OS DADOS DESEJADOS
3.1.
3.2.
4.
SOBRE SQL
VISÃO GERAL DE UM BANCO DE DADOS RELACIONAL
COLUNAS E LINHAS
ENTIDADES E CHAVE PRIMÁRIA
CHAVE PRIMÁRIA COMPOSTA
CLÁUSULAS SELECT E FROM
CLÁUSULA WHERE
3.2.1.
PREDICADOS RELACIONAIS
3.2.2.
OUTROS PREDICADOS RELACIONAIS
3.2.3.
VINCULANDO VÁRIOS PREDICADOS: AND E OR
9
9
10
11
11
13
QUERIES: MANIPULANDO DADOS
14
4.1.
4.2.
14
15
15
15
16
16
OPERADORES ARITMÉTICOS
FUNÇÕES
4.2.1.
FUNÇÕES AGREGADAS
4.2.2.
FUNÇÕES NÃO AGREGADAS
4.2.3.
FUNÇÕES DE SEQÜÊNCIAS DE CARACTERES
4.2.4.
FUNÇÕES DE DATA E HORA
ORGANIZANDO O RESULTADO
17
5.1.
5.2.
5.3.
17
17
18
CLÁUSULA GROUP BY
CLÁUSULA HAVING
CLÁUSULA ORDER BY
JUNÇÕES: QUERIES QUE ENVOLVEM MAIS DE UMA TABELA
19
6.1.
6.2.
6.3.
6.4.
EQUIJUNÇÕES
JUNÇÕES EXTERNAS
AUTO-JUNÇÕES
OUTROS TIPOS DE JUNÇÕES
20
21
21
23
QUERIES EM OUTRAS DECLARAÇÕES
23
7.1.
7.2.
23
23
DECLARAÇÃO UNION
UTILIZANDO QUERIES PARA INCLUIR DADOS
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 1
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
8.
ALTERANDO TABELAS E DADOS
24
8.1.
24
24
25
25
25
26
26
27
27
27
8.2.
9.
10.
ALTERANDO OS DADOS
8.1.1.
ATUALIZANDO DADOS EM UMA LINHA
8.1.2.
ELIMINANDO LINHAS
8.1.3.
GRAVANDO E DESFAZENDO ALTERAÇÕES
ALTERANDO UMA TABELA
8.2.1.
ELIMINANDO UMA COLUNA
8.2.2.
INCLUINDO UMA COLUNA
8.2.3.
MODIFICANDO UMA COLUNA
8.2.4.
TROCANDO O NOME DE UMA TABELA OU COLUNA
8.2.5.
ELIMINANDO UMA TABELA
UTILIZANDO ÍNDICE PARA MELHORAR A PERFORMANCE
28
9.1.
9.2.
9.3.
9.4.
28
28
29
29
UTILIZANDO UM ÍNDICE
UTILIZANDO UM ÍNDICE ÚNICO
UTILIZANDO UM ÍNDICE CONCATENADO
APAGANDO UM ÍNDICE
PROGRAMANDO EM SQL
30
10.1.
10.2.
30
30
PORQUE SQL EMBUTIDA
UTILIZANDO A FERRAMENTA ACCESS
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 2
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
1.Introdução
1.1.
Sobre SQL
Um banco de dados é como um arquivo eletrônico, ou seja, tem a mesma função que qualquer outro
arquivo — armazenar registros. A única diferença é que no banco de dados os registros são armazenados
eletronicamente.
Para termos acesso aos registros armazenados ou mesmo cadastrar novos registros, precisamos de um
sistema que gerencie o banco de dados. Este sistema gerenciador de banco de dados é que torna possíveis
as operações com o conteúdo do arquivo, como — “Traga-me este arquivo”, “Atualize este registro”.
Existem vários tipos de sistemas de gerenciamento de banco de dados (SGBD ou DBMS), representando
diversas abordagens relativas às tarefas de acesso às informações contidas no banco de dados, preservação
da integridade dos dados, acompanhamento dos usuários e manutenção da segurança. Para o nosso estudo,
porém, podemos classificar todos os sistemas em dois tipos: relacionais e não relacionais, embora seja
visível o predomínio da abordagem relacional nos novos sistemas do mercado.
Em um sistema relacional, os dados são armazenados e representados exclusivamente em tabelas. Em
nenhum momento faz-se necessário recorrer a outras estruturas, como árvores hierárquicas, para ter acesso
aos dados.
A linguagem SQL — o nome é a sigla de Structured Query Language (Linguagem de Query Estruturada)
— é uma linguagem para gerenciar um sistema de banco de dados relacional. Não só é uma linguagem,
como também tem sido tão utilizada que pode ser considerada um padrão. Consiste de uma série de
declarações, adotadas de comum acordo, que nos permitem realizar diversas operações.
Temos que usar a expressão comum acordo porque, embora uma SQL padrão tenha sido criada pelo
Instituto de Padrões Nacionais Americanos (ANSI), todas as implementações particulares da SQL
personalizam a linguagem de várias formas. Tais implementações complementam a linguagem padrão com
novos tipos de declarações ou expressões e muitas vezes adaptam as declarações padronizadas às
necessidades específicas.
1.2.
Visão Geral de um Banco de Dados Relacional
Sistemas relacionais caracterizam um grande avanço no armazenamento e no gerenciamento de grandes
quantidades de dados. A principal razão para isso é que, em um sistema relacional, pode-se reduzir bastante
o armazenamento de dados redundantes. Na verdade, idealmente falando, em um sistema projetado
segundo os princípios teóricos da abordagem relacional, a redundância não deve existir. Nenhum
relacionamento entre dois itens de dados (uma pessoa possui um endereço, por exemplo) deve aparecer
mais de uma vez em cada um banco de dados.
Na prática, os sistemas apenas se aproximam deste ideal, por várias razões, e podemos dizer que
normalmente contêm alguns dados repetidos em vários lugares. Mas mesmo em um sistema relacional que
apenas se aproxime da situação ideal, minimizar a redundância dos dados acarreta dois benefícios básicos:
em primeiro lugar, os dados podem ser reorganizados e combinados de forma mais facilmente em novos
relacionamentos; não ficam presos aos relacionamentos em que foram armazenados. Em segundo lugar, a
atualização torna-se muito mais fácil, pois poucos itens de dados têm que ser atualizados, o que reduz a
incidência de erros.
Todos os dados de um sistema relacional são armazenados e exibidos em tabelas. Programas de planilhas e
sistemas de banco de dados não relacionais também usam tabelas, portanto não é uma característica
exclusiva dos sistemas relacionais. Mas há algo que distingue a forma como os sistemas relacionais usam
tabelas. Esta distinção deriva-se da definição e da utilização do banco de dados segundo certos princípios
teóricos da abordagem relacional. Mais adiante iremos abordar tais princípios.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 3
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
1.3.
Colunas e Linhas
Qualquer informação refere-se a qualquer coisa, e talvez o primeiro princípio da abordagem relacional seja
o de todas as informações contidas em uma tabela devem estar sempre relacionadas a exemplos de “um
tipo de coisa”. Este princípio destingue o uso relacional de tabelas.
Por exemplo, a tabela HOSPEDES abaixo contém informações sobre os sócios de um clube de tratamento
da forma física, selecionado, conceituado e imaginário chamado Visual Spa (fig. 1.1).
Fig. 1.1 - HOSPEDES
NOME
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
JANE FYUNDAI
STELLA SHIELDS
ROGÉRIO NUNES
SEXO
M
M
F
F
F
M
BIOTIPO
M
M
G
G
M
M
ALTURA
1,67
1,72
1,65
1,80
1,65
1,78
A tabela possui quatro colunas — NOME, SEXO, BIOTIPO e ALTURA e 6 linhas.
Contém informações sobre os hóspedes do Spa; cada coluna vertical possui dados referentes a uma
característica ou atributo dos hóspedes. Os atributos em que estamos interessados são nome, sexo, biotipo e
altura de cada hóspede; por isso destinamos uma coluna a cada um deles.
Esta é a função das colunas verticais de uma tabela: conter informações sobre os atributos das entidades a
que se refere a tabela.
Cada linha horizontal da tabela HOSPEDE contém as informações sobre todos os atributos referentes a um
determinado hóspede. Portanto, enquanto a coluna NOME exibe os nomes de todos os hóspedes da tabela e
a coluna SEXO o sexo de todos os hóspedes e assim por diante em relação às outras colunas, a linha em
que aparece o nome José Augusto contém informações apenas referentes aos atributos do hóspede chamado
José Augusto. Mais adiante introduziremos um novo conceito relacional: o de chave primária.
1.4.
Entidades e Chave Primária
No mundo real, você teria inúmeras razões para querer tratar cada hóspede do Visual Spa individualmente:
se você não considerá-los separadamente, não poderá designar os quartos adequadamente, elaborar os
programas de emagrecimento segundo as necessidades de cada um, preparar as faturas corretamente, e
assim por diante. Pelas mesmas razões, você terá que ter os hóspedes também individualizados no banco de
dados. Em termos práticos, isto significa que as linhas da tabela devem ser diferenciadas. Se você não
puder diferenciar a linha de José Augusto da de Maurício de Souza, o banco de dados não lhe dará
condições para designar os quartos adequadamente, elaborar os programas de emagrecimento segundo as
necessidades de cada um, preparar as faturas corretamente, e assim por diante.
Para que uma linha possa se distinguir das outras, tem que ser de alguma forma diferente, ou seja, tem que
ter uma característica que a identifique. Em um sistema relacional, esta característica identificadora não
pode ser identificador externo, como a posição que a linha ocupa em relação às outras; tem que ser um dos
próprios componentes da linha. Como a linha só consiste de itens de dados, temos que tentar localizar
dentre os dados da linha aquele que poderá identificá-la univocamente.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 4
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Em outras palavras, temos que procurar por uma coluna (ou grupo de colunas) que apresente um conteúdo
diferente em cada linha — dados que são duplicados em duas linhas. Esta característica então servirá para
identificar a linha da mesma forma que usamos um nome para identificar uma pessoa.
Volte à tabela HÓSPEDE (fig. 1.1). Observe que nem todos os atributos, ou colunas, são igualmente
suficientes para identificar as linhas. Por exemplo, não basta saber apenas o sexo de um hóspede que você
queira identificar se este atributo é compartilhado por metade dos seus hóspedes. Da mesma forma, se
soubermos o biotipo de um hóspede teremos um grupo mais reduzido mas não conseguiremos localizar um
hóspede em particular.
O problema é que as colunas SEXO e BIOTIPO contêm valores duplicados. Quando duas linhas contêm o
mesmo atributo, este atributo não pode ser usado para distinguir as linhas entre si.
Concluindo, a única coluna que pode servir de atributo identificador é a coluna NOME. Como não contém
valores duplicados, as informações nela contidas são por si só suficientes para distinguir a linha de um
hóspede na tabela.
Descrevemos, na realidade, uma diferença entre os dois tipos de colunas. O primeiro tipo está baseado em
um atributo que identifique univocamente ou defina uma linha. O segundo tipo baseia-se em atributos
descritivos que fornecem informações, mas não são suficientes para identificar uma linha ou entidade.
A coluna (ou grupo de colunas) baseada em um atributo identificador de uma linha é chamada de Chave ou
Chave Primária. A chave de uma tabela lhe permite identificar as linhas individualmente, definindo
também as entidades às quais a tabela se refere. Um banco de dados relacional todas as tabelas tem que ter
uma chave primária que identifique cada linha.
1.5.
Chave Primária Composta
A chave primária pode consistir de mais de uma coluna, as vezes não podemos distinguir as linhas uma das
outras usando apenas uma coluna, mais sim mais de uma.
O exemplo a seguir lista o nome de todos os hóspedes que chegaram ou saíram no período entre 01 e
27/08/97; a data de chegada de cada hóspede, a data de saída — se houver —, o quarto e o técnico de cada
hóspede e por último o desconto — se houver.
Fig. 1.2 – LISTA DE HÓSPEDES
NOME
JANE FYUNDAI
MARCELO FREITAS
ALEXANDRE GOMES
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
JANE FYUNDAI
STELLA SHIELDS
ALEXANDRE GOMES
QUARTO
4
2
1
3
5
6
7
8
9
TÉCNICO
JÚLIO
BRUNA
RICARDO
JÚLIO
RICARDO
BRUNA
SERENA
SERENA
BRUNA
CHEGADA
15-08-1997
26-08-1997
14-08-1997
15-08-1997
25-08-1997
15-08-1997
24-08-1997
25-08-1997
17-08-1997
SAÍDA
17-08-1997
DESCTO
0.20
0.10
16-08-1997
19-08-1997
20-08-1997
0.15
0.05
23-08-1997
0.15
0.20
Nenhuma das colunas por si só poderá funcionar como chave primária, pois todas elas possuem valores
duplicados, inclusive NOME: Alexandre Gomes e Jane Fyundai estiveram hospedados duas vezes e por
isso aparecem duas vezes na lista. Para estabelecermos uma chave para esta tabela, teremos que usar duas
ou mais colunas conjuntamente. Este tipo de chave, envolvendo duas ou mais colunas, denomina-se chave
composta ou chave primária composta.
No exemplo (Fig. 1.2) as colunas que melhor se candidatam a formar chave composta são NOME e
CHEGADA. O NOME e a CHEGADA combinados lhe permite distinguir uma linha da outra, ou seja, não
há linhas com os valores de NOME e CHEGADA iguais.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 5
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
2.A Linguagem SQL
SQL é uma linguagem própria para a realização de operações relacionais. Em linhas gerais, é uma
linguagem para gerenciar um sistema relacional. Através das declarações SQL, dados são recuperados,
atualizados ou eliminados, colunas são alteradas, tabelas são criadas e eliminadas, e qualquer outras
modificações são efetuadas na estrutura de um banco de dados. As declarações em SQL podem ser
subdivididas em quatro categorias: queries, definição de dados, manipulação de dados e controle de dados.
2.1.
Criando uma Tabela
Usamos a declaração CREATE TABLE para criar uma tabela. As declarações abaixo criam as duas tabelas
que já vimos anteriormente — HÓSPEDES e LISTA DE HÓSPEDES. A tabela HÓSPEDES contém os
dados de todos os hóspedes do Visual Spa, passados e atuais. A tabela LISTA DE HÓSPEDES registra as
datas de entrada e saída, quartos ocupados, etc., de todas as pessoas que se hospedaram no spa no período
de 01 e 27/08/1997.
Observe que as declarações a seguir apenas criam as tabelas. Preenchê-las com dados constitui uma outra
operação, que veremos posteriormente.
CREATE TABLE HOSPEDES (NOME VARCHAR(25) NOT NULL, SEXO VARCHAR(1),
BIOTIPO VARCHAR(1), ALTURA DECIMAL(3,2));
CREATE TABLE LISTA_DE_HOSPEDES (NOME VARCHAR(25) NOT NULL, QUARTO
VARCHAR(3), TECNICO VARCHAR(8), CHEGADA DATE NOT NULL, SAIDA DATE,
DESCONTO DECIMAL(2,2);
As tabelas HOSPEDES e LISTA_DE_HOSPEDES já existem, embora vazias. A tabela HOSPEDES
consiste das quatro colunas NOME, SEXO, BIOTIPO e ALTURA; a LISTA_DE_HOSPEDES consiste
das seis colunas NOME, QUARTO, TECNICO, CHEGADA, SAIDA e DESCONTO.
Observe que ambas das declarações CREATE TABLE terminam com um ponto e vírgula (;). Este é o sinal
de que a declaração terminou. Embora esta não seja propriamente uma característica da SQL, todas as
implementações interativas da SQL exigem um sinal indicativo de final de declaração.
Algumas interfaces interativas, oferecem duas formas de marcar o término de uma declaração. A primeira e
colocar um ponto e vírgula seguido de um retorno <ENTER> no final da última linha da declaração; a
segunda e colocar na linha seguinte à última linha da declaração uma barra (/) e um retorno <ENTER>
como mostramos nos exemplos abaixo:
SELECT NOME, ALTURA
FROM HOSPEDES;
ou
SELECT NOME, ALTURA
FROM HOSPEDES
/
Ambos os métodos são muito usados, nesta apostila terminamos as declarações normalmente com o ponto e
vírgula. Não existe regra quanto ao número de linhas de uma declaração SQL. Poderíamos ter escrito a
declaração toda em uma linha só, o que ocuparia menos espaço. O ponto e vírgula ou a barra é obrigatório
somente no final da última linha da declaração.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 6
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
2.2.
Identificadores e Atributos
Observe os dois traços sublinhados ( ___ ) ligando as três palavras que compões o nome da tabela
LISTA_DE_HOSPEDES. O traço sublinhado é um meio convencional para representar o espaço nos
nomes de tabelas ou colunas que contêm mais de uma palavra. Ele têm por finalidade ligar uma palavra à
outra, fazendo com que formem apenas um conjunto de caracteres, podendo se reconhecidas portanto como
partes integrantes de um único nome.
2.3.
Tipos de Dados
A SQL padrão da ANSI reconhece dois tipos genéricos de dados — seqüências (“strings”) de caracteres de
dados numéricos —, e oferece vários tipos particulares com diferentes características para atender às
necessidades de cada coluna. Estes incluem CHAR (ou CHARACTER), para seqüências de caracteres, e os
tipos NUMERIC, DECIMAL, INTEGER, SMALLINT, FLOAT, REAL, DOUBLE PRECISION, para
dados numéricos.
Existem diversos tipos de dados implementados para duas outras categorias de dados. Uma delas abrange
os dados tipo data e hora, representados em SQL Base pelos tipos DATE, TIME, TIMESTAMP; a outra é
o tipo de dado LONG VARCHAR ou LONG, tipo genérico que pode armazenar qualquer categoria de
dados, inclusive dados binários. Em SQL Base, os dados do tipo LONG podem ter um tamanho virtual
qualquer (bilhões de bytes); em outras implementações, o limite normalmente é de 64 Kbytes.
2.3.1. Dados Caracteres “Strings”
O tipo CHAR armazena seqüências de caracteres de tamanho fixo que consistem de letras, caracteres
especiais ou dígitos, e cujo tamanho não pode ultrapassar 254 bytes. O tamanho máximo (até 255
caracteres) a ser aceito em uma coluna deve ser definido quando, ao criá-la, especificamos o atributo de
tamanho. Todos os dados desta coluna são armazenados com o tamanho indicado quando da sua definição.
Em SQL padrão, quando um dado possui um tamanho menor ao especificado para a coluna, espaços em
branco são acrescentados à direita. Em SQL Base, estes dados podem definidos como CHAR ou
VARCHAR.
2.3.2. Dados Numéricos
O tipo NUMBER armazena números de 1.0E-100 a 1.0E+100, com, no máximo, 22 dígitos decimais de
precisão. As colunas deste tipo não possuem indicações de precisão e escala em suas definições.
O tipo DECIMAL armazena números de 1.0E-100 a 1.0E+100, com no máximo 22 dígitos decimais de
precisão, mas, ao contrário do tipo NUMBER, as colunas DECIMAL têm que ter indicações de precisão e
escala em suas definições.
O tipo INTEGER armazena um número com até dez dígitos de precisão. Não são aceitos dígitos
fracionários; os algarismos à direita do ponto decimal são truncados.
O tipo SMALLINT armazena um número com até cinco dígitos de precisão. Da mesma forma que o tipo
INTEGER, não são aceitos dígitos fracionários, os quais são truncados.
O tipo FLOAT armazena um número decimal de ponto flutuante de dupla precisão ou precisão simples,
dependendo da especificação de tamanho.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 7
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
2.3.3. Dados Data e Hora
O tipo DATE armazena datas, que podem ser codificadas e exibidas em diversos formatos.
O tipo TIME armazena horas, registrando até os microssegundos, sendo que podem também ser
codificados e exibidas em diversos formatos.
O tipo TIMESTAMP é usado em colunas criadas para armazenar data e hora ao mesmo tempo. Este tipo é
uma combinação dos formatos DATE e TIME, sendo que os dados contêm ambos os componentes data e
hora.
Veja na tabela seguinte os formatos de datas convencionais mais importantes:
Tabela – Formatos de Datas
Nome
Formato
Exemplo
Organizações de Padrões Intern.
aaaa-mm-dd
1998-10-30
Padrão IBM — EUA (USA)
mm/dd/aaaa
10/30/1998
Padrão IBM — Europa (EUR)
dd.mm.aaaa
30.10.1998
Padrão Industrial Japonês (JIS)
aaaa-mm-dd
1998-10-30
Veja na tabela seguinte os formatos de datas convencionais mais importantes:
Tabela – Formatos de Horas
2.4.
Nome
Formato
Exemplo
Organizações de Padrões Intern.
hh.mm.ss
14.30.02
Padrão IBM — EUA (USA)
hh:mm AM ou PM
2:30 PM
Padrão IBM — Europa (EUR)
hh.mm.ss
14.30.02
Padrão Industrial Japonês (JIS)
hh:mm:ss
14:30:02
Incluindo Dados
A declaração CREATE TABLE mostrada no início apenas criou as tabelas HOSPEDES e
LISTA_DE_HOSPEDES, sem preenchê-las com dados. Para incluir dados nas tabelas, usamos uma outra
declaração ou comando.
Na linguagem SQL a única forma de incluir dados é através da declaração INSERT, que normalmente
inclui uma única linha de cada vez. Só pode ser utilizada para incluir várias linhas se nela for inserida uma
query que recupere de outra tabela os dados a serem incluídos.
A declaração SQL abaixo ilustra a inclusão de uma única linha de dados na tabela
LISTA_DE_HOSPEDES. A linha consiste de seis itens de dados, separados por vírgulas – um item para
cada uma das seis colunas da tabela LISTA_DE_HOSPEDES. O primeiro item de dados é incluído na
primeira coluna da tabela, o segundo item na segunda coluna, e assim por diante, como se segue:
INSERT INTO LISTA_DE_HOSPEDES (NOME, QUARTO, TECNICO, CHEGADA, SAIDA,
DESCONTO)
VALUES (‘CLOVIS ALMEIDA’, ‘3’, ‘JULIO’, 13-08-1997, 17-08-1997, .2;
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 8
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Como estamos incluindo dados em todas as colunas da tabela LISTA_DE_HOSPEDES, poderíamos omitir
a lista dos nomes das colunas após o nome da tabela. Esta lista só é indispensável caso estejamos incluindo
dados em apenas algumas colunas e não em todas; temos então que indicar os nomes das colunas que
receberão dados. Nomeamos todas as colunas neste exemplo simplesmente para facilitar análise da
declaração.
Observe que os dados referentes às colunas NOME, QUARTO e TECNICO estão entre apóstrofes (‘). Isto
se deve ao fato de que os dados das três colunas são do tipo VARCHAR. Dados CHAR ou VARCHAR
usados em declarações SQL devem aparecer entre apóstrofes.
3.Queries: Obtendo os Dados Desejados
A query é o meio através do qual podemos pesquisar e obter dados das tabelas de um banco de dados. A
seguir abordamos os seus elementos básicos, inclusive as duas cláusulas essenciais obrigatórias em todas as
queries e uma terceira que contém a especificação das linhas em que estão os dados desejados.
3.1.
Cláusulas SELECT e FROM
Por mais básica que seja, uma query tem que ter pelo menos dois componentes — uma cláusula SELECT e
uma cláusula FROM. Em uma query simples, a cláusula SELECT enumera os nomes das colunas que
contêm os dados desejados, e a FROM especifica as tabelas em que estão localizadas as colunas.
A query mais simples possível seleciona todos os dados de todas as colunas da tabela. Entretanto, podemos
restringir a cláusula SELECT de modo que se obtenha dados de apenas algumas colunas, ou, de outras
formas, acrescentando qualificações. Podemos citar na cláusula SELECT colunas de mais de uma tabela,
além de especificar várias operações a serem executadas sobre os dados e exibir os resultados das mesmas.
O resultado da query é exibido em forma de tabela e é, às vezes, chamado de tabela resultado. As linhas do
resultado representam os dados que atendem às condições estabelecidas ou são o produto das operações
especificadas na query. Se não houver dados em nenhuma destas situações, não serão selecionadas linhas.
Analisemos um exemplo de uma query e seu resultado.
SELECT NOME, QUARTO, TECNICO, CHEGADA, SAIDA, DESCONTO
FROM LISTA_DE_HOSPEDES;
NOME
JANE FYUNDAI
MARCELO FREITAS
JANE FYUNDAI
ALEXANDRE GOMES
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
STELLA SHIELDS
ALEXANDRE GOMES
QUARTO
3
2
4
1
7
5
6
8
9
TÉCNICO
JÚLIO
BRUNA
SERENA
RICARDO
JÚLIO
RICARDO
BRUNA
SERENA
BRUNA
CHEGADA
15-08-1997
26-08-1997
24-08-1997
14-08-1997
15-08-1997
25-08-1997
15-08-1997
25-08-1997
17-08-1997
SAÍDA
17-08-1997
DESCTO
0.20
0.10
16-08-1997
19-08-1997
20-08-1997
23-08-1997
0.15
0.05
0.15
0.20
A query acima solicita todas as linhas de dados para todas as colunas da tabela LISTA_DE_HOSPEDES.
Não acrescentamos qualificações, e, portanto, o resultado contém todos os dados destas colunas.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 9
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Incidentemente, podemos usar um asterisco (*) em vez de nomes de colunas na cláusula SELECT. O
asterisco representa “os valores de todas as colunas”. Usar o asterisco é o mesmo que nomear todas as
colunas de uma tabela ou mais tabelas, na sua ordem original. Portanto, ao invés de digitar todos os nomes
de colunas como fizemos no exemplo anterior, poderíamos ter obtido o mesmo resultado codificando a
query assim:
SELECT *
FROM LISTA_DE_HOSPEDES;
Podemos selecionar de apenas algumas colunas e omitir outras. A query a seguir obtém os dados somente
da coluna NOME:
SELECT NOME
FROM LISTA_DE_HOSPEDES;
Podemos evitar que dados sejam exibidos duplicados, usando a palavra-chave DISTINCT imediatamente
após a palavra “SELECT” na cláusula SELECT para suprimir as linhas duplicadas do resultado. No
exemplo abaixo a palavra-chave DISTINCT foi acrescentada na query anterior:
SELECT DISTINCT NOME
FROM LISTA_DE_HOSPEDES;
A palavra-chave DISTINCT suprime apenas as linhas duplicadas do resultado, e não valores duplicados.
3.2.
Cláusula WHERE
A cláusula WHERE reduz o escopo da query focalizando apenas determinadas linhas. Ao invés de retornar
os valores das expressões da cláusula SELECT de todas as linhas, uma query com uma cláusula WHERE
retorna apenas os valores das linhas que atendam às condições especificadas na cláusula WHERE.
Em outras palavras, uma query contendo a cláusula WHERE tem essencialmente o seguinte formato:
SELECT o valor das expressões
FROM estas tabelas
somente nas linhas WHERE estas condições foram atendidas.
As condições da cláusula WHERE são chamadas de condições de pesquisa. O exemplo abaixo seleciona
dados das colunas NOME e TECNICO da tabela LISTA_DE_HOSPEDES somente nas linhas em que o
técnico for a Bruna. Em outras palavras, a query lista os nomes (e técnicos) de todas as pessoas cujo o
técnico seja a Bruna:
SELECT NOME, TECNICO
FROM LISTA_DE_HOSPEDES
WHERE TECNICO = ‘BRUNA’;
NOME
MARCELO FREITAS
BIANCA OLIVEIRA
ALEXANDRE GOMES
TÉCNICO
BRUNA
BRUNA
BRUNA
Não é obrigatório citar na cláusula WHERE somente colunas que apareçam na cláusula SELECT. A query
anterior funcionaria da mesma forma se eliminássemos a coluna TECNICO da cláusula SELECT.
SELECT NOME
FROM LISTA_DE_HOSPEDES
WHERE TECNICO = ‘BRUNA’;
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 10
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
NOME
MARCELO FREITAS
BIANCA OLIVEIRA
ALEXANDRE GOMES
3.2.1. Predicados Relacionais
No exemplo anterior, TECNICO = ‘BRUNA’ é um predicado relacional. O sinal de igualdade (=) é um
operador relacional simples.
Existem nove operadores relacionais simples, que podem formar nove tipos de predicados relacionais
simples para expressar condições de pesquisa. Existem ainda cinco outros tipos de predicados relacionais.
Discutiremos todos os tipos existentes nos próximos tópicos.
Predicados Relacionais Simples
A query utilizada no último exemplo foi:
SELECT NOME
FROM LISTA_DE_HOSPEDES
WHERE TECNICO = ‘BRUNA’;
Como já foi dito, a query contém um operador relacional simples, o sinal de igualdade. Seu significado
seria traduzido assim:
SELECT o valor de NOME e TECNICO
FROM tabela LISTA_DE_HOSPEDES
somente nas linhas WHERE o valor de TECNICO seja igual a ‘BRUNA’;
Os operadores relacionais simples são os nove abaixo:
=
!=
<>
igual a
não igual a
não igual a
>
!>
<
maior que
não maior que
menor que
!<
>=
<=
não menor que
maior ou igual a
menor ou igual a
3.2.2. Outros Predicados Relacionais
Além dos operadores já discutidos, há outros cinco que também podem ser usados para formar predicados
relacionais. São eles:
BETWEEN...AND
IS NULL
LIKE
IN
O operador BETWEEN especifica os dados compreendidos em uma determinada faixa. Pode ser usado
tanto com números quanto com datas. Por exemplo, poderíamos obter os nomes e os percentuais de
desconto de todos os hóspedes que tenham recebido de 10 a 20 por cento inclusive, como se segue:
SELECT NOME, DESCONTO
FROM LISTA_DE_HOSPEDES
WHERE DESCONTO BETWEEN .10 AND .20;
NOME
JANE FYUNDAI
MARCELO FREITAS
MAURÍCIO DE SOUZA
STELLA SHIELDS
ALEXANDRE GOMES
DESCTO
0.20
0.10
0.15
0.15
0.20
Podemos solicitar também os nomes e as datas de saída de todos os hóspedes que saíram do Spa entre 19 e
24 de agosto:
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 11
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
SELECT NOME, SAIDA
FROM LISTA_DE_HOSPEDES
WHERE SAIDA BETWEEN 19-08-1997 AND 24-08-1997;
NOME
JOSE AUGUSTO
BIANCA OLIVEIRA
ALEXANDRE GOMES
SAIDA
19-08-1997
20-08-1997
23-08-1997
O operador IS NULL nos permite selecionar as linhas em que o valor de um determinado campo seja
desconhecido. Por exemplo, as linhas de vários hóspedes ficaram com a SAIDA em branco. Podemos
selecionar os nomes destes hóspedes utilizando o operador IS NULL.
SELECT NOME, SAIDA
FROM LISTA_DE_HOSPEDES
WHERE SAIDA IS NULL;
NOME
MARCELO FREITAS
JANE FYUNDAI
STELLA SHIELDS
SAIDA
O operador LIKE nos permite utilizar caracteres máscara para comparar dados em uma condição de
pesquisa. Em vez de os dados terem que ser idênticos, podemos especificar que sejam apenas semelhantes
em algum aspecto.
Podemos usar os dois caracteres máscara abaixo com o operador LIKE:
_ (sublinhado)
* (asterisco)
Vale por qualquer caractere único
Vale por qualquer seqüência de caracteres
No contexto de um LIKE, o caractere de sublinhado ( _ ) funciona analogamente ao ponto de interrogação
(?) do MS-DOS, que serve de caractere máscara em nomes de arquivos, e o símbolo de percentual (%)
funciona analogamente ao asterisco (*).
O exemplo de query abaixo usa o operador LIKE e um caractere máscara para selecionar todos os nomes
que comecem com a seqüência de caracteres ‘MA%’;
SELECT NOME
FROM LISTA_DE_HOSPEDES
WHERE NOME LIKE ‘MA%’;
NOME
MARCELO FREITAS
MAURICIO DE SOUZA
A próxima query seleciona todos os nomes que tenham a letra J na primeira posição e N na quarta, não
importando quais sejam os outros caracteres.
SELECT NOME
FROM LISTA_DE_HOSPEDES
WHERE NOME LIKE ‘J__N’;
NOME
JANE FYUNDAI
Mais um exemplo:
SELECT NOME
FROM LISTA_DE_HOSPEDES
WHERE NOME LIKE ‘_AR_E%’;
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 12
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
NOME
MARCELO FREITAS
O último operador a ser discutido neste tópico é o IN, que nos permite selecionar dados que se encaixem
em um conjunto ou uma lista de valores. Os valores podem ser indicados explicitamente em uma
declaração, como nos exemplos a seguir.
A query abaixo seleciona o nome, o técnico e o quarto de cada hóspede cujo o técnico esteja presente na
lista ‘BRUNA’, ‘JULIO’:
SELECT NOME, TECNICO, QUARTO
FROM LISTA_DE_HOSPEDES
WHERE TECNICO IN (‘BRUNA’, ‘JULIO’);
NOME
JANE FYUNDAI
MARCELO FREITAS
JOSÉ AUGUSTO
BIANCA OLIVEIRA
ALEXANDRE GOMES
TÉCNICO
JÚLIO
BRUNA
JÚLIO
BRUNA
BRUNA
QUARTO
3
2
4
6
9
Todos os operadores relacionais também podem ser utilizados com o NOT. Na query abaixo, selecionamos
o nome, o técnico e o quarto dos hóspedes cujo o técnico não esteja incluído na lista:
SELECT NOME, TECNICO, QUARTO
FROM LISTA_DE_HOSPEDES
WHERE TECNICO NOT IN (‘BRUNA’, ‘JULIO’);
NOME
ALEXANDRE GOMES
MAURÍCIO DE SOUZA
JANE FYUNDAI
STELLA SHIELDS
QUARTO
1
5
7
8
TÉCNICO
RICARDO
RICARDO
SERENA
SERENA
3.2.3. Vinculando Vários Predicados: AND e OR
Podemos restringir ainda mais a seleção de linhas usando uma cláusula WHERE com mais de uma
condição de pesquisa. Isto se faz possível através dos operadores AND e OR.
Na query abaixo, selecionamos o nome, o técnico e o desconto dos hóspedes que ainda estão no Spa e cujo
o técnico seja Serena:
SELECT NOME, TECNICO, DESCONTO
FROM LISTA_DE_HOSPEDES
WHERE SAIDA IS NULL AND TECNICO = ‘SERENA’
NOME
JANE FYUNDAI
STELLA SHIELDS
TÉCNICO DESCTO
SERENA
SERENA
0.15
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 13
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Podemos acrescentar inúmeras condições à cláusula WHERE usando os operadores AND e OR. A próxima
query acrescenta vários componentes:
SELECT NOME, QUARTO, TECNICO, CHEGADA, SAIDA
FROM LISTA_DE_HOSPEDES
WHERE SAIDA IS NULL
AND TECNICO = ‘ROBERTO’
AND QUARTO > 16
AND CHEGADA < 20-08-97;
4.Queries: Manipulando Dados
A linguagem SQL não nos limita a selecionar os dados exatamente na forma que aparecem nas tabelas.
Como mencionamos anteriormente, podemos usar queries também para selecionar os resultados de
operações realizadas sobre os dados.
Neste tópico, descrevemos três elementos que viabilizam as operações realizadas sobre os dados em uma
query. São eles:
Operador aritmético;
Funções agregadas;
Funções não agregadas.
Em cada caso, o operador ou função é usado com constantes, nomes de colunas e assim por diante para
formar uma expressão nova.
4.1.
Operadores Aritméticos
São quatro os operadores aritméticos que podem formar expressões:
+
*
/
adição
subtração
multiplicação
divisão
A query abaixo, usamos o operador de soma para adicionar 0.05 (uma constante) ao valor corrente de
DESCONTO na linha de Marcelo Freitas. A cláusula SELECT contém duas expressões: NOME e a
expressão formada pelo operador aritmético, DESCONTO + 0.05. A tabela resultado deverá conter duas
colunas, uma para cada expressão:
SELECT NOME, DESCONTO + 0.05
FROM LISTA_DE_HOSPEDES
WHERE NOME = ‘MARCELO FREITAS’
NOME
MARCELO FREITAS
DESCTO
0.15
Embora as regras variem de implementação para implementação, algumas permitem ainda o uso de
operadores aritméticos com dados do tipo data e hora. Em SQL Base, por exemplo, a query abaixo pode ser
usada para determinar por quantos dias ficaram no Spa os hóspedes que já foram embora. Este número é
obtido subtraindo-se a data de chegada de saída. Outras implementações permitem queries semelhantes,
mas não idênticas.
SELECT NOME, SAIDA - CHEGADA
FROM LISTA_DE_HOSPEDES
WHERE NOME = ‘MARCELO FREITAS’
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 14
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
4.2.
Funções
As funções constituem mais uma forma de usar queries para manipular os dados das tabelas. Uma função
retorna o valor resultante de uma determinada operação realizada sobre o seu argumento (ou argumentos).
Uma função, como o seu argumento, representa um valor e é portanto uma expressão.
4.2.1. Funções Agregadas
A característica marcante das funções agregadas é que produzem um único valor a partir de uma coluna
inteira de dados. Portanto, enquanto qualquer outro tipo de expressão retorna um valor para cada linha, as
funções agregadas retornam um valor que representa um agregado dos valores referentes às várias linhas.
Por esta razão, são também chamadas de funções de colunas.
Existem cinco funções agregadas. São elas:
AVG(argumento)
MAX(argumento)
MIN(argumento)
SUM(argumento)
COUNT(argumento)
Retorna a média dos valores do argumento
Retorna o maior valor do argumento
Retorna o menor valor do argumento
Retorna o somatório dos valores do argumento
Retorna a número de linhas do argumento
As funções agregadas normalmente usam como argumento um nome de coluna ou uma expressão que
tenha um nome de coluna como componente, mas podemos usá-las com qualquer expressão numérica ou
de datas.
A query a seguir lê todos os valores da coluna DESCONTO e fornece os percentuais médio, máximo e
mínimo de desconto oferecidos aos hóspedes do Visual Spa. Como as função AVG, MÁX, MIN e SUM
ignoram valores nulos, o valor AVG (média) é realmente o desconto médio apenas daqueles hóspedes que
obtiveram algum desconto:
SELECT AVG(DESCONTO), MAX(DESCONTO), MIN(DESCONTO)
FROM LISTA_DE_HOSPEDES;
AVG(DESCONTO)
0.115635
MAX(DESCONTO)
0.20
MIN(DESCONTO)
0.05
Outros exemplos:
SELECT MIN(DESCONTO) * AVG(SAIDA-CHEGADA)
FROM LISTA_DE_HOSPEDES
WHERE TECNICO = ‘SENERA’;
4.2.2. Funções Não Agregadas
As funções não agregadas diferem das agregadas pelo fato de que não fornecem um único valor a partir de
uma coluna inteira de dados. Em vez disto, as funções não agregadas, como todas as expressões que já
discutimos (exceto as funções agregadas), retornam um valor para cada linha.
Em SQL Base, as funções agregadas começam sempre com o caractere “@”, mas esta convenção só
pertence ao SQL Base. Nos outros aspectos, a sintaxe das funções não agregadas é igual a das agregadas: a
função é seguida de seu argumento entre parênteses, por exemplo, @PROPER(‘JOSE AUGUSTO’).
Da mesma forma que as funções agregadas, as não agregadas podem ser usadas uma dentro da outra, de
modo que o resultado da função interna seja usado como argumento da externa. Por exemplo, na função:
@PROPER(@LEFT(‘JOSE AUGUSTO’, 4))
@LEFT retorna os cinco primeiros caracteres da seqüência ‘JOSE AUGUSTO’ (‘JOSE’), os quais
compões o argumento da função @PROPER. Esta função coloca apenas a primeira letra de cada palavra de
seu argumento em letra maiúscula e as restantes em letra minúscula, como na representação de nomes
próprios. Neste caso, @PROPER converte ‘JOSE’ em ‘Jose’.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 15
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
4.2.3. Funções de Seqüências de Caracteres
Como as funções não agregadas variam muito de implementação para implementação, esta apostila não se
dispões a examiná-las detalhadamente. Apresentamos neste próximo tópico apenas alguns exemplos
representativos oferecidos pelo SQL Base.
O exemplo abaixo usa a função @LENGTH (seqüência de caracteres). Colocamos a expressão seqüência
de caracteres entre parênteses para indicar que esta função utiliza seqüências de caracteres como
argumentos. Ela retorna o número de caracteres existentes no argumento. Neste caso, usamos a função para
informar o número de caracteres de cada NOME da tabela LISTA_DE_HOSPEDES:
SELECT NOME, @LENGTH(NOME)
FROM LISTA_DE_HOSPEDES;
NOME
JANE FYUNDAI
MARCELO FREITAS
JOSÉ AUGUSTO
BIANCA OLIVEIRA
ALEXANDRE GOMES
@LENGTH (NOME)
12
15
12
15
15
SELECT NOME, @PROPER(@LENGTH(NOME,5))
FROM LISTA_DE_HOSPEDES;
NOME
JANE FYUNDAI
MARCELO FREITAS
JOSÉ AUGUSTO
BIANCA OLIVEIRA
ALEXANDRE GOMES
@PROPER(@LENGTH (NOME,5))
jane
marce
josé
bianc
alexan
4.2.4. Funções de Data e Hora
São funções que retornam informações sobre uma coluna de dados do tipo data ou hora ou geram
resultados do tipo data ou hora.
A função de data @DAY(data), por exemplo, seleciona apenas o dia do mês da DATA:
SELECT NOME, CHEGADA, @DAY(CHEGADA)
FROM LISTA_DE_HOSPEDES;
NOME
JANE FYUNDAI
MARCELO FREITAS
ALEXANDRE GOMES
JOSÉ AUGUSTO
CHEGADA
15-08-1997
26-08-1997
14-08-1997
15-08-1997
@DAY(CHEGADA)
15
26
14
15
Queries semelhantes podem ser criadas com as funções @MONTH, @YEAR, @HOUR, @MINUTE e
@SECOND.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 16
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
5.Organizando o Resultado
5.1.
Cláusula GROUP BY
A cláusula GROUP BY reúne diferentes linhas do resultado de uma query em conjuntos de acordo com as
colunas nela mencionadas, chamadas colunas formadoras de grupos. As linhas são “agrupadas” de duas
formas, ou em dois aspectos.
A query abaixo exemplifica a primeira forma, na qual todas as linhas que contêm o mesmo valor na
primeira coluna especificada são exibidas em grupos no resultado. Neste caso, a primeira coluna formadora
de grupo é TECNICO. Todas as linhas que tenham o mesmo valor na coluna TECNICO aparecerão juntas
no resultado:
SELECT TECNICO, NOME
FROM LISTA_DE_HOSPEDES
GROUP BY TECNICO, NOME;
TÉCNICO
BRUNA
BRUNA
BRUNA
JÚLIO
JÚLIO
RICARDO
RICARDO
SERENA
SERENA
NOME
MARCELO FREITAS
BIANCA OLIVEIRA
ALEXANDRE GOMES
JANE FYUNDAI
JOSÉ AUGUSTO
ALEXANDRE GOMES
MAURÍCIO DE SOUZA
JANE FYUNDAI
STELLA SHIELDS
Se houvesse linhas em que a coluna TECNICO estivesse em branco, ou seja, com um valor nulo para
TECNICO, também seriam agrupadas. E as linhas são agrupadas da mesma maneira para cada coluna
formadora de grupos subseqüente, embora isto não esteja aparente no exemplo dados pois só contém duas
colunas.
Obs.: As funções agregadas — AVG, SUM, MAX, MIN e COUNT — não podem ser usadas em cláusulas
GROUP BY pois geram um único valor e por isso não podem agrupar linhas.
A cláusula GROUP BY também pode ser usada em queries contendo uma cláusula WHERE. Neste caso, a
GROUP BY é codificada depois da cláusula WHERE. Por exemplo, a query abaixo exibe os nomes dos
hóspedes que chegaram depois do dia 15 de agosto por técnico:
SELECT TECNICO, NOME
FROM LISTA_DE_HOSPEDES
WHERE CHEGADA > 15-08-97
GROUP BY TECNICO, NOME;
5.2.
Cláusula HAVING
A cláusula HAVING nos permite estreitar a área de atuação da cláusula GROUP BY da mesma forma que
a cláusula WHERE estreita a área de atuação da cláusula SELECT, ou seja, através de uma condição de
pesquisa.
Ao contrário da cláusula WHERE, no entanto, a cláusula HAVING pode conter funções agregadas.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 17
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Uma nova tabela, HOSPEDES_PS, será usada nos exemplos deste tópico. Criamos uma tabela com a
declaração CREATE TABLE abaixo. Esta tabela se destina a registrar as pesagens periódicas dos hóspedes
do Visual Spa.
CREATE TABLE HOSPEDE_PS (HOSPEDE VARCHAR(25) NOT FULL, PESO
DECIMAL(4,1), QUANDO DATE);
Chamamos a coluna DATE de QUANDO porque “DATE” é uma palavra reservada. As palavras
reservadas não podem ser usadas como nomes de colunas ou outros identificadores, a não ser que entre
aspas.
Após a inclusão dos dados, a tabela HOSPEDE_PS tem a seguinte aparência:
SELECT * FROM HOSPEDE_PS
NOME
JANE FYUNDAI
MARCELO FREITAS
ALEXANDRE GOMES
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
JANE FYUNDAI
MARCELO FREITAS
ALEXANDRE GOMES
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
PESO
68
59
86
87
68.5
67.5
55
84
84
67
QUANDO
14-08-97
14-08-97
15-08-97
15-08-97
15-08-97
16-08-97
16-08-97
17-08-97
17-08-97
17-08-97
A tabela contém dois registros de peso para cada estada: um na data de entrada e outro na data de saída. A
query a seguir indica os hóspedes que tiveram uma diferença acima de um entre seu peso mínimo e seu
peso máximo. Observe a presença de funções agregadas na cláusula HAVING.
SELECT HOSPEDE, MIN(PESO), MAX(PESO) – MIN(PESO)
FROM HOSPEDE_PS
GROUP BY HOSPEDE
HAVING MAX(PESO) – MIN(PESO) > 1;
NOME
MARCELO FREITAS
ALEXANDRE GOMES
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
MIN(PESO)
55
84
84
67
MAX(PESO MAX(PESO)-MIN(PESO)
)
59
4
86
2
87
3
68.5
1.5
Passemos para um outro exemplo. Esta query solicita o número de hóspedes orientados por cada técnico
que trabalhou com mais de dois hóspedes:
SELECT HOSPEDE, COUNT(NOME)
FROM HOSPEDE_PS
GROUP BY HOSPEDE
HAVING CONT(NOME) > 2;
5.3.
Cláusula ORDER BY
A cláusula ORDER BY nos permite classificar as linhas do resultado alfabética e numericamente, em
ordem crescente ou decrescente. O default é a ordem crescente. A cláusula ORDER BY é sempre a última
cláusula da query.
No exemplo a seguir, obtemos os nomes dos hóspedes classificados em ordem decrescente colocando a
palavra DESC na cláusula ORDER BY depois do nome da coluna a ser ordenada. Usamos a palavra-chave
DISTINCT para suprimir as linhas duplicadas:
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 18
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
SELECT DISTINCT NOME
FROM LISTA_DE_HOSPEDES
ORDER BY NOME DESC;
NOME
STELLA SHIELDS
MAURÍCIO DE SOUZA
MARCELO FREITAS
JOSÉ AUGUSTO
JANE FYUNDAI
JANE FYUNDAI
BIANCA OLIVEIRA
ALEXANDRE GOMES
ALEXANDRE GOMES
As classificações são, por default, efetuadas em ordem crescente, a não ser que seja indicada a palavrachave DESC após o nome da coluna. Porém, podemos também explicitar a ordem crescente para uma
determinada coluna, usando-se a palavra-chave ASC após o nome da coluna na cláusula ORDER BY.
6.Junções: Queries que Envolvem Mais de uma Tabela
Por muitas vezes, os dados que desejamos não estão contidos em uma só tabela. Por exemplo, para obter a
altura e o nome do técnico de Bianca Oliveira, temos que pesquisar em duas tabelas. O nome de seu técnico
está registrado na tabela LISTA_DE_HOSPEDES, mas sua altura só está contida na tabela HOSPEDES.
Esta última, a qual já foi vista em tópicos anteriores, tem a seguinte aparência:
SELECT * FROM HOSPEDES;
NOME
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
JANE FYUNDAI
STELLA SHIELDS
ROGÉRIO NUNES
SEXO
M
M
F
F
F
M
BIOTIPO
M
M
G
G
M
M
ALTURA
1,67
1,72
1,65
1,80
1,65
1,78
A query a seguir obtém a altura de Rogério Nunes :
SELECT NOME, ALTURA
FROM HOSPEDES
WHERE NOME = ‘BIANCA OLIVEIRA’;
NOME
BIANCA OLIVEIRA
ALTURA
1,65
A próxima query obtém seu técnico da tabela LISTA_DE_HOSPEDES:
SELECT NOME, TECNICO
FROM LISTA_DE_HOSPEDES
WHERE NOME = ‘BIANCA OLIVEIRA’;
NOME
BIANCA OLIVEIRA
TECNICO
BRUNA
Podemos, no entanto, obter as mesmas informações de uma só vez através de uma query chamada junção.
Uma junção é uma query que obtém dados de mais de uma tabela ao mesmo tempo, baseando-se na
condição de junção indicada na cláusula WHERE. Temos abaixo uma junção que fornece a altura e o
técnico de todos os hóspedes:
SELECT HOSPEDES.NOME, ALTURA, TECNICO
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 19
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
FROM HOSPEDES, LISTA_DE_HOSPEDES
WHERE HOSPEDES.NOME = LISTA_DE_HOSPEDES.NOME;
NOME
JANE FYUNDAI
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
STELLA SHIELDS
TÉCNICO ALTURA
JÚLIO
1,80
JÚLIO
1,67
RICARDO
1,72
BRUNA
1,65
SERENA
1,65
Podemos traduzir a query da seguinte maneira: “Para todas as linhas de HOSPEDES e
LISTA_DE_HOSPEDES
cujo
o
valor
de
HOSPEDES.NOME
seja
igual
ao
de
LISTA_DE_HOSPEDES.NOME, obtenha os respectivos NOME e ALTURA de HOSPEDES e o
TECNICO de LISTA_DE_HOSPEDES.”
6.1.
Equijunções
A última query que analisamos é um exemplo de “equijunção” — uma junção baseada em uma condição de
igualdade. Outros tipos de predicados relacionais podem constituir outros tipos de condição de junção, dos
quais veremos alguns exemplos. Porém de antemão sabemos que o tipo mais comum é o de igualdade — a
“equijunção”.
Para que possamos dar um exemplo um pouco diferente, criaremos uma nova tabela, QUARTOS, que irá
conter detalhes das acomodações do Visual Spa. A declaração utilizada para criá-la é a seguinte:
CREATE TABLE QUARTOS (QUARTO VARCHAR(3), NOME VARCHAR(15),
TAXA FLOAT, DESCRICAO LONG VARCHAR);
A tabela em questão preenchida com dados, excetuando-se a coluna de tipo LONG, tem a seguinte
aparência:
SELECT QUARTO, NOME, TAXA
FROM QUARTOS;
QUARTO
1
2
3
4
5
NOME
ANA PAULA
CARMEM SOUZA
CRISTIANO BEZERRA
MARCONE ALMEIDA
MARIA FERREIRA
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
TAXA
300
300
250
325
250
Página 20
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Segue-se então o exemplo de “equijunção”. Para efeito de demonstração, a “equijunção” encontra-se em
uma cláusula AND. Observe, também, que nenhuma das duas colunas unidas, QUARTO da tabela
QUARTOS e da LISTA_DE_HOSPEDES, aparece na lista do SELECT.
SELECT LISTA_DE_HOSPEDES.NOME, QUARTOS.NOME, QUARTOS.TAXA,
LISTA_DE_HOSPEDES.DESCONTO
FROM QUARTOS, LISTA_DE_HOSPEDES
WHERE LISTA_DE_HOSPEDES.NOME = ‘JANE FYUNDAI’
AND QUARTOS.QUARTO = LISTA_DE_HOSPEDES.QUARTO;
LISTA_DE_HOSPEDES. QUARTOS.NOME
NOME
JANE FYUNDAI
MARCONE ALMEIDA
6.2.
QUARTOS.TAXA
325
LISTA_DE_HOSPEDES.
DESCTO
0.20
Junções Externas
Suponhamos que quiséssemos saber o nome, o sexo, o biotipo, a altura e o técnico de cada um dos
hóspedes do Visual Spa. Os técnicos são indicados na tabela LISTA_DE_HOSPEDES, a qual contém
informações sobre hóspedes atuais; as outras informações estão contidas na tabela HOSPEDES, que
contém os registros de todos os hóspedes, atuais e passados.
Podemos, para isso, usar esta query, uma simples “equijunção”:
SELECT HOSPEDES.NOME, SEXO, BIOTIPO, ALTURA, TECNICO
FROM HOSPEDES, LISTA_DE_HOSPEDES
WHERE HOSPEDES.NOME = LISTA_DE_HOSPEDES.NOME;
NOME
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
JANE FYUNDAI
STELLA SHIELDS
ROGÉRIO NUNES
CLINT WESTWOOD
SEXO
M
M
F
F
F
M
M
BIOTIPO
M
M
G
G
M
M
M
ALTURA
1,67
1,72
1,65
1,80
1,65
1,78
1,85
TECNICO
JULIO
RICARDO
BRUNA
JULIO
SERENA
SERENA
RICARDO
Uma junção externa nos permite unir tabelas através de colunas com números diferentes de linhas, sem que
as linhas comuns às duas sejam excluídas da tabela resultado. Ao contrário, as linhas exclusivas de apenas
uma das tabelas são incluídas no resultado, com valores nulos em quaisquer colunas da outra tabela, onde
aquelas linhas não existem.
O recurso de junções externas só existe em poucas implementações da linguagem SQL. Entretanto, por
considerá-lo importante e como possivelmente será implementado em maior escala no futuro, vamos
analisar como é efetuado este tipo de junção no SQL Base.
A sintaxe SQL Base para converter o exemplo anterior em uma junção externa a fim de incluir as demais
linhas da tabela não contidas no resultado é simples: basta acrescentar um sinal de adição (+) ao lado do
nome da coluna que não possui as linhas externas, ou seja, aquela na qual incluiremos valores nulos no
resultado, na condição de junção. Ex.:
SELECT HOSPEDES.NOME, SEXO, BIOTIPO, ALTURA, TECNICO
FROM HOSPEDES, LISTA_DE_HOSPEDES
WHERE HOSPEDES.NOME = LISTA_DE_HOSPEDES.NOME(+);
6.3.
Auto-Junções
Por muitas vezes, precisamos fazer uma junção de uma tabela com ela mesma. Esta é uma forma de
tratarmos uma única tabela como se fosse na verdade duas tabelas, a fim de possibilitar certos tipos de
queries.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 21
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Suponhamos que quiséssemos selecionar todos os hóspedes que tenham obtido o mesmo percentual de
desconto que Maurício de Souza. Todas as informações que desejamos estão na tabela
LISTA_DE_HOSPEDES, que tem a seguinte aparência:
SELECT * FROM LISTA_DE_HOSPEDES;
NOME
JANE FYUNDAI
MARCELO FREITAS
JANE FYUNDAI
ALEXANDRE GOMES
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
STELLA SHIELDS
ALEXANDRE GOMES
QUARTO
3
2
4
1
7
5
6
8
9
TÉCNICO
JÚLIO
BRUNA
SERENA
RICARDO
JÚLIO
RICARDO
BRUNA
SERENA
BRUNA
CHEGADA
15-08-1997
26-08-1997
24-08-1997
14-08-1997
15-08-1997
25-08-1997
15-08-1997
25-08-1997
17-08-1997
SAÍDA
17-08-1997
DESCTO
0.20
0.10
16-08-1997
19-08-1997
20-08-1997
23-08-1997
0.15
0.05
0.15
0.20
Poderíamos, evidentemente, usar uma query para selecionar DESCONTO onde NOME fosse igual a
“MAURICIO DE SOUZA” e, em seguida, uma outra que selecionasse NOME e DESCONTO onde
DESCONTO fosse igual ao resultado da primeira query. Mais digamos que quiséssemos optar por uma
forma mais elegante e menos trabalhosa – usar uma única query.
Esta tarefa parece bastante simples. Poderíamos começar a construir a query assim:
SELECT NOME, DESCONTO
FROM LISTA_DE_HOSPEDES
WHERE DESCONTO = ...?
Entretanto, neste ponto chegamos a um impasse. Queremos dizer WHERE DESCONTO = (o desconto de
Maurício de Souza), mas não vemos como.
Observe como seria fácil resolver este problema se, ao invés de lida com apenas uma tabela, estivéssemos
lidando com duas, a fim de obter o desconto de Maurício de Souza de uma e as informações sobre os
outros hóspedes da outra. Então, usando as letras A e B para distinguir duas tabelas na realidade idênticas,
teríamos a seguinte query:
SELECT A.NOME, A.DESCONTO
FROM LISTA_DE_HOSPEDES A, LISTA_DE_HOSPEDES_B
WHERE A.DESCONTO = B.DESCONTO
AND B.NOME = ‘MAURICIO DE SOUZA’;
NOME
MAURÍCIO DE SOUZA
STELLA SHIELDS
DESCTO
0.15
0.15
Como você pode comprovar através do resultado, esta é a forma que temos para resolver este tipo de query
— chamada “auto-junção”.
Os nomes de tabelas temporários, denominados nomes correlatos ou títulos (labels), são os elementoschaves que permitem que a junção ocorra a partir de uma única tabela. Os nomes correlatos são definidos
na lista do FROM, na qual estabelecemos que a tabela em questão passa a ser conhecida por estes nomes. A
partir daí, todos os nomes de colunas que quisermos usar terão como prefixo estes nomes correlatos.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 22
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
6.4.
Outros Tipos de Junções
Quando a condição de pesquisa utilizada não está baseada em uma relação de igualdade e sim de “maior
que” (>).
Eventualmente junções como esta, não baseadas em uma relação de igualdade, são conhecidas como “não
equijunções”. O termo engloba todas as junções que utilizem qualquer operador relacional exceto o de
igualdade ( = ).
Nem todas as implementações SQL comportam este tipo de junção.
7.Queries em Outras Declarações
7.1.
Declaração UNION
A palavra-chave UNION vincula queries sucessivas e une os seus resultados. As linhas duplicadas são
suprimidas.
As queries vinculadas têm que ter o mesmo número de elementos na lista do SELECT, e os tipos de dados
e tamanho têm que coincidir coluna a coluna. Por exemplo, se a primeira coluna da lista do SELECT da
primeira query for do tipo VARCHAR(25), então a primeira coluna da lista do SELECT de cada uma das
queries subseqüentes na declaração UNION tem que ser também do tipo VARCHAR(25). Não poderiam
ser colunas VARCHAR(8) e nem colunas numéricas ou de data e hora. Se, por fim, uma das colunas for
definida como NOT NULL, todas as colunas a serem unidas a ela terão que ser também como NOT NULL.
O exemplo a seguir une os nomes dos hóspedes da tabela HOSPEDES com os da tabela
LISTA_DE_HOSPEDES. Como as linhas duplicadas são eliminadas, o resultado será exatamente o mesmo
que o da primeira query.
Ambas da colunas são do tipo VARCHAR.
SELECT NOME FROM HOSPEDES
UNION
SELECT NOME FROM LISTA_DE_HOSPEDES;
NOME
JOSÉ AUGUSTO
MAURÍCIO DE SOUZA
BIANCA OLIVEIRA
JANE FYUNDAI
STELLA SHIELDS
ROGÉRIO NUNES
As declarações SELECT em uma UNION podem conter funções e cláusulas WHERE e GROUP BY, e
uma cláusula ORDER BY também pode ser acrescentada à UNION como um todo.
Não há limites para o número de queries cujos os resultados podem ser unidos através de uma UNION.
7.2.
Utilizando Queries para Incluir Dados
Abordemos agora o último uso do SELECT embutido em outra declaração. Além de servir para selecionar
dados para uma query externa, pode ser usado para incluir dados quando a declaração externa for um
INSERT.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 23
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Suponhamos que quiséssemos criar uma tabela HOSPEDES_HOMENS, idêntica à HOSPEDES, à exceção
de que, ao invés de listar o sexo, o biotipo e a altura de todos os hóspedes, antigos e atuais,
HOSPEDES_HOMENS contém apenas os dados dos hóspedes do sexo masculino (e, portanto, não listará
o sexo). A tabela é criada pela declaração abaixo:
CREATE TABLE HOSPEDES_HOMENS (NOME VARCHAR(25), BIOTIPO VARCHAR(1),
ALTURA INTEGER);
Agora temos que incluir dados. Os dados que desejamos já estão cadastrados na tabela HOSPEDES e
podem ser extraídos e incluídos através de uma declaração INSERT contendo uma query.
INSERT INTO HOSPEDES_HOMENS
SELECT NOME, BIOTIPO, ALTURA
FROM HOSPEDES
WHERE SEXO = ‘M’;
As únicas restrições existentes neste caso são as seguintes:
— O número de colunas do SELECT tem que ser o mesmo que o da declaração INSERT ou, como nosso
exemplo, o mesmo número de colunas contidas na tabela, se as colunas não forem mencionadas.
— O tipo e o tamanho dos dados selecionados têm que ser compatíveis com as especificações das colunas
na tabela de destino. Por exemplo, números podem ser incluídos em uma coluna de tipo caractere, mas
o contrário não é aceito.
8.Alterando Tabelas e Dados
Até agora lidamos a maior parte do tempo com as queries — declarações SELECT que nos permitem, de
uma forma ou de outra, obter dados de uma tabela. Nesta etapa da apostila, discutiremos exemplos de dois
outros tipos de declarações SQL: declarações de manipulação de dados, usadas para alterar os dados de
um banco de dados, e declarações de definição de dados, que servem para fazer alterações na estrutura do
banco de dados.
8.1.
Alterando os Dados
Uma declaração de manipulação de dados que já vimos é o INSERT, cuja função é incluir novas linhas.
Além do INSERT, há mais duas outras declarações de manipulação de dados: UPDATE e DELETE. Como
o INSERT as duas declarações nos permitem alterar o conteúdo do banco de dados. UPDATE altera linhas
existentes e DELETE as exclui do banco de dados.
8.1.1. Atualizando Dados em uma Linha
Suponhamos que um dia Alexandre nos informasse que teria mudado seu nome para André e que gostaria
que trocássemos também em nossos registros o seu nome antigo pelo nome novo. Poderíamos usar a
declaração UPDATE abaixo para fazer esta alteração na tabela LISTA_DE_HOSPEDES:
UPDATE LISTA_DE_HOSPEDES
SET NOME = ‘ANDRE’
WHERE NOME = ‘ALEXANDRE’;
O nome da tabela ou visão a ser atualizada é indicado na primeira linha do exemplo. Na segunda linha
aparece o nome da coluna a ser atualizada e o tipo de alteração, e na terceira a condição de pesquisa. Como
nas queries, se não houver condições de pesquisa, a operação será executada em todas as linhas.
Suponhamos que André também queira trocar o quarto 9, o qual teve que dividir com Jane Fyundai, pelo 7,
que espera poder ocupar sozinha; e digamos que também consiga obter mais 2% de desconto, além dos 20
originais.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 24
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Podemos usar a declaração UPDATE para realizar as duas alterações de uma só vez. A segunda condição
de pesquisa, especificando a data de chegada, é necessária pois existem dois quartos ocupados pelo André
em LISTA_DE_HOSPEDES, e só queremos alterar um deles.
UPDATE LISTA_DE_HOSPEDES
SET QUARTO = ‘7’, DESCONTO = DESCONTO + 0.02
WHERE NOME = ‘ALEXANDRE’
AND CHEGADA = 17-08-97;
Como podemos observar no exemplo, é possível alterar mais de uma coluna ao mesmo tempo e usar
expressões aritméticas para indicar o valor novo.
8.1.2. Eliminando Linhas
Podemos remover linhas de uma tabela, desde que seja atualizável, através da declaração DELETE. Da
mesma forma que com o UPDATE, qualquer linha que seja eliminada de uma visão será também eliminada
da tabela original.
A declaração abaixo elimina da tabela LISTA_DE_HOSPEDES todas as linhas de hóspedes que tenham
uma data de saída registrada:
DELETE FROM LISTA_DE_HOSPEDES
WHERE SAIDA IS NOT NULL;
Para eliminar todas as linhas de uma tabela, não especifique uma condição de pesquisa.
8.1.3. Gravando e Desfazendo Alterações
Nos dois tópicos anteriores, fizemos várias alterações no banco de dados. Podemos desfazê-las através da
declaração:
ROLLBACK;
Com esta declaração recuperamos de volta as linhas que havíamos excluído, e os dados alterados voltaram
a ser exatamente o que eram antes da alteração. Se tivéssemos eliminado as tabelas por inteiro, elas também
seriam recuperadas.
8.2.
Alterando uma Tabela
Além de alterar os dados de uma tabela, a SQL nos permite também alterar a sua estrutura, através da
declaração ALTER TABLE. Uma outra declaração, DROP, que será discutida no final deste tópico, serve
para eliminar a tabela completamente.
O número exato de características da tabela que podemos alterar varia em função da implementação da
declaração ALTER TABLE. Ela possui várias cláusulas ou continuações, correspondentes às operações
que serão executadas, que variam de implementação para implementação. A SQL padrão, assim como a
maioria das implementações, limita as opções em duas, ADD e MODIFY. O SQL Base complementa este
padrão com três outras continuações.
Suponhamos, por exemplo, que começássemos uma declaração ALTER TABLE da seguinte maneira:
ALTER TABLE LISTA_DE_HOSPEDES
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 25
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Em SQL Base, temos cinco opções de cláusulas ou continuações para complementar a declaração,
dependendo da operação desejada:
ADD (incluir)
MODIFY (modificar)
DROP (eliminar)
RENAME (trocar o nome de)
RENAME TABLE (trocar nome tabela)
uma nova coluna
o tamanho de uma coluna ou se a coluna
deverá aceitar valores nulos.
uma coluna existente
uma coluna existente
Comecemos pela primeira opção: eliminar uma coluna.
8.2.1. Eliminando uma Coluna
Suponhamos que decidíssemos não dar mais descontos a nenhum hóspede. Podemos eliminar a coluna
DESCONTO da LISTA_DE_HOSPEDES da seguinte forma:
ALTER TABLE LISTA_DE_HOSPEDES
DROP DESCONTO;
Poderíamos, se desejado, eliminar mais de uma coluna da tabela em uma só declaração, separando os
nomes das colunas por vírgulas, da mesma forma que na lista do SELECT. Por exemplo:
ALTER TABLE LISTA_DE_HOSPEDES
DROP QUARTO, SAIDA;
Entretanto, não poderíamos usar a declaração ALTER TABLE para alterar mais de uma tabela ao mesmo
tempo.
Uma coluna que possua um índice não pode ser eliminada, a não ser que o índice seja eliminado antes.
8.2.2. Incluindo uma Coluna
Usamos a cláusula ADD da declaração ALTER TABLE para incluir uma coluna.
Incluir uma coluna é mais trabalhoso do que apagar uma outra, pois temos que especificar o tipo de dado
que irá conter, o tamanho (quando necessário) e se aceitará ou não valores nulos, exatamente da mesma
forma que procedemos quando definimos as colunas de uma tabela ao criá-la.
A declaração a seguir inclui uma nova coluna DESCONTO igual à que eliminamos:
ALTER TABLE LISTA_DE_HOSPEDES
ADD DESCONTO DECIMAL(2,2);
Especificamos que a nova coluna é do tipo DECIMAL e o seu tamanho é (2,2). Como queríamos que a
coluna aceitasse valores nulos, não mencionamos NOT NULL, mas poderíamos tê-lo feito.
A nova coluna DESCONTO está vazia, isto é, só contém valores nulos, porque até agora não foram
incluídos dados nela. Mesmo que tivéssemos especificado NOT NULL, a coluna conteria valores nulos
iniciais. NOT NULL apenas garante que não serão aceitos valores nulos em futuras atualizações.
Como na exclusão poderíamos incluir mais de uma coluna de uma só vez. A declaração a seguir inclui as
colunas SAIDA e GARCOM:
ALTER TABLE LISTA_DE_HOSPEDES
ADD SAIDA DATE, GARCOM VARCHAR(10);
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 26
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
8.2.3. Modificando uma Coluna
A cláusula MODIFY da declaração ALTER TABLE é que nos permite aumentar o tamanho de uma coluna
de tamanho variável. No entanto, não podemos reduzir o seu tamanho e alterar o seu tipo.
Por exemplo, podemos fazer com que uma coluna VARCHAR(5) passe a ser VARCHAR(10), mas não
que passe a ser do tipo INTEGER.
Podemos, ainda, fazer com que uma coluna que não aceite valores nulos passe a aceitar e também podemos
fazer o inverso, desde que a coluna não contenha nulos.
Por exemplo, não contém valores nulos na coluna TECNICO de LISTA_DE_HOSPEDES; então
poderíamos, se necessário, fazer com que TECNICO passasse a ser NOT NULL. Já não podemos fazer o
mesmo com a coluna DESCONTO, pois ela contém valores nulos.
A declaração abaixo altera o tamanho da coluna TECNICO de 8 para 25 e define a coluna como NOT
NULL:
ALTER TABLE LISTA_DE_HOSPEDES
MODIFY TECNICO VARCHAR(25) NOT NULL;
Podemos alterar mais de uma coluna ao mesmo tempo, separando-as por vírgulas na cláusula MODIFY:
ALTER TABLE LISTA_DE_HOSPEDES
MODIFY TECNICO VARCHAR(30) NULL, NOME NULL;
8.2.4. Trocando o Nome de uma Tabela ou Coluna
As duas últimas opções da declaração ALTER TABLE são RENAME, para trocar o nome de colunas,
RENAME TABLE de tabelas.
Os exemplos a seguir trocam o nome da coluna GARCOM para SERVENTE:
ALTER TABLE LISTA_DE_HOSPEDES
RENAME GARCOM SERVENTE;
Não é necessário informar o tipo de dado ou o tamanho da coluna, porque estes mantêm-se os mesmos.
RENAME TABLE funciona da mesma forma. A única diferença é que como o nome da tabela já esta
indicado na cláusula ALTER TABLE, só temos que especificar o novo nome na cláusula RENAME
TABLE.
A declaração abaixo altera o nome da tabela LISTA_DE_HOSPEDES para LISTA:
ALTER TABLE LISTA_DE_HOSPEDES
RENAME TABLE LISTA;
8.2.5. Eliminando uma Tabela
Para eliminar totalmente uma tabela, usamos a declaração DROP.
DROP se assemelha ao ALTER TABLE quanto ao fato de serem várias declarações em uma só.
Dependendo de como você o formula, o DROP pode eliminar uma tabela, uma visão, um índice ou um
sinônimo. Neste tópico, descrevemos apenas a eliminação de tabelas e visões. Índices e sinônimos serão
estudados mais adiante.
A declaração a seguir apaga a tabela QUARTOS:
DROP TABLE QUARTOS;
Quando uma tabela é eliminada do banco de dados, todas as visões derivadas dela e índices e sinônimos
definidos para ela, assim como os privilégios designados em função dela, também desaparecem.
Se tentarmos executar uma query na tabela QUARTOS agora, receberemos uma mensagem de erro
indicando que a tabela não existe.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 27
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
9.Utilizando Índice para Melhorar a Performance
Observe que as linhas da tabela LISTA_DE_HOSPEDES estão listadas em uma ordem aleatória, ou seja,
em nenhuma das colunas os valores seguem a uma ordem alfabética ou numérica. Ao invés disso,
aparecem na ordem em que foram incluídas.
Se quisermos procurar um determinado nome, teremos que percorrer toda a coluna NOME até encontrá-lo.
O mecanismo de busca do sistema de banco de dados não difere em muito nosso método. Ele também
percorreria os dados da coluna até localizar o nome desejado.
O uso de índices acelera a procura. Quando criamos índices para uma coluna, ela é classificada de tal forma
que, sempre que for mencionada em uma query, o sistema usará o índice para ter acesso direto aos dados
desejados, ao invés de vasculhar a coluna toda. Os índices são então muito úteis às queries que se referem a
uma única linha. Em termos gerais os índices são úteis em qualquer coluna que seja consultada
freqüentemente.
Criamos um índice com a declaração CREATE INDEX, e ele é automaticamente atualizado quando a
coluna (ou colunas) a ele associada (s) sofre (m) alguma alteração.
Um índice só deixa de existir se for executada a declaração DROP INDEX ou se a tabela para qual foi
criada foi eliminada.
Podemos criar um índice para apenas uma coluna ou várias em conjunto. A segunda forma de índice é
conhecida como concatenado ou composto. Podemos criar quantos índices quisermos, não há limites. No
entanto, devemos considerar o fato de que ocupam bastante espaço em disco e seria aconselhável não criar
tantos índices a ponto de confundir o otimizador do banco de dados.
O otimizador é um subsistema do sistema de banco de dados que seleciona os caminhos de acesso e decide
qual a melhor maneira de extrair os dados solicitados por uma query. É o otimizador que escolhe quais
índices disponíveis deve usar, se houver; o usuário não precisa se preocupar com isso.
9.1.
Utilizando um Índice
A query abaixo pesquisa duas tabelas para obter o nome, o técnico e a altura de todos os hóspedes.
SELECT A.NOME, TECNICO, ALTURA
FROM LISTA_DE_HOSPEDES A, HOSPEDES B
WHERE A.NOME = B.NOME;
Usaremos a declaração CREATE INDEX para criar um índice, especificando primeiro o nome da tabela,
LISTA_DE_HOSPEDES, e, em seguida, entre parênteses, a coluna ou as colunas a serem indexadas.
Podemos incluir também a palavra-chave ASC ou DESC ao lado do nome da coluna para identificar a
indexação em ordem crescente ou decrescente. O default é a ordem crescente.
CREATE INDEX NOME_ID
ON LISTA_DE_HOSPEDES (NOME);
O índice acelera a execução da query anterior em 13% em um PC/AT.
9.2.
Utilizando um Índice Único
A query que utilizamos envolve uma junção de duas tabelas. Podemos criar um índice na segunda tabela
também.
Não especificamos que NOME_ID deveria ser um índice único, pois a coluna
LISTA_DE_HOSPEDES.NOME contém nomes repetidos. “Existem hóspedes que já fizeram duas visitas
no Spa”. Um índice único não pode ser criado em uma coluna ou grupo de colunas que contenha linhas
duplicadas.
A tabela HOSPEDES, porém, representa o nosso arquivo contendo todos os hóspedes passados e atuais, no
qual cada hóspede só aparece uma vez. Além disso, queremos nos certificar de que a coluna NOME da
tabela HOSPEDES só contém o nome de cada hóspede uma única vez, para que possamos tornar o nosso
índice único.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 28
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
A declaração abaixo cria um índice único na coluna NOME da tabela HOSPEDES:
CREATE UNIQUE INDEX NOME1_IND
ON HOSPEDES (NOME);
Chamamos este índice de NOME1_IND porque já temos o NOME_IND, e os índices têm que ter nomes
diferentes, mesmo que sejam criados em colunas de tabelas diferentes.
Devido a presença de um índice único, qualquer valor duplicado não será aceito. Agora com os dois índices
que criamos, a query do início deste tópico tem a sua execução acelerada em 20% em um PC/AT.
9.3.
Utilizando um Índice Concatenado
Para exemplificar o nosso próximo exemplo criaremos uma nova tabela chamada QUADRO_DE_PESOS,
a qual fornece os pesos mínimo e máximo aceitáveis para homens e mulheres de acordo com o biotipo, e a
altura em metros. A declaração para criá-la é a seguinte:
CREATE TABLE QUADRO_DE_PESOS (ALTURA DECIMAL(3,2), SEXO CHAR(1),
BIOTIPO CHAR(1), PS_MIN DECIMAL(3,1), PS_MAX DECIMAL (3,1));
Com os dados incluídos separadamente, a tabela tem o seguinte aspecto:
SELECT * FROM QUADRO_DE_PESOS;
ALTURA
1,67
1,72
1,65
1,80
1,65
1,78
1,85
SEXO
M
M
F
F
F
M
M
BIOTIPO
M
M
G
G
M
M
M
PS_MIN
56
57
57.5
72
73.5
75
60
PS_MAX
58.5
59.5
60
78.5
80
82.5
66
Sempre que quisermos consultar a faixa aceitável de peso de uma pessoa na tabela QUADRO_DE_PESOS,
teremos que fornecer ao sistema os valores das três colunas ALTURA, SEXO e BIOTIPO.
A query a seguir executa esta consulta. Seleciona o nome, o técnico e a faixa aceitável de peso de todos os
hóspedes. NOME e TECNICO vêm da LISTA_DE_HOSPEDES; a altura, o sexo e o biotipo são obtidos
da tabela HOSPEDES e são usados para localizar a respectiva faixa no QUADRO_DE_PESOS:
SELECT A.NOME, TECNICO, PS_MIN, PS_MAX
FROM LISTA_DE_HOSPEDES A, HOSPEDES B, QUADRO_DE_PESOS C
WHERE A.NOME = B.NOME
AND B.SEXO = C.SEXO
AND B.ALTURA = C.ALTURA
AND B.BIOTIPO = C.BIOTIPO;
Podemos reduzir significamente o tempo de execução da query criando um índice concatenado abrangendo
as colunas ALTURA, SEXO e BIOTIPO:
CREATE INDEX PESO_IND
ON QUADRO_DE_PESOS (ALTURA, SEXO, BIOTIPO);
O índice concatenado reduz o tempo de execução da query em 38% em um PC/AT.
9.4.
Apagando um Índice
Qualquer índice de uma tabela é eliminado automaticamente quando a tabela é excluída. Para eliminar um
índice manualmente, usamos a declaração DROP INDEX, que é a mesma declaração usada para apagar
tabelas. Só agora concluiremos a explicação desta declaração.
A declaração abaixo apaga o índice PESO_IND que criamos na tabela QUADRO_DE_PESOS:
DROP INDEX PESO_IND;
A tabela onde foi criado o índice não é afetada pela sua eliminação.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 29
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
10.Programando em SQL
No início desta apostila, vimos como usar a linguagem SQL de modo interativo, ou seja, como executar as
declarações SQL diretamente do teclado. Agora, focalizaremos o tópico programação em SQL —
declarações SQL embutidas em programas escritos em outra linguagem, como por exemplo, C ou COBOL.
10.1. Porque SQL Embutida
Como foi mencionado na introdução, SQL não é uma linguagem de programação e nem uma linguagem
interativa. Não podemos escrever programas em SQL diretamente. Temos que executá-las através de um
programa que “converse” com o sistema de banco de dados e realize as operações que a SQL não foi
projetada para realizar.
10.2. Utilizando a Ferramenta ACCESS
Para que possamos entender melhor a SQL, utilizaremos um Sistema de Gerenciamento de Banco de
Dados bem conhecido o Microsoft Access. A ferramenta Access permite-nos utilizar comandos SQL para
manipulação de dados, portanto poderemos utilizar os comandos aprendidos até agora.
O Microsoft Access possui um arquivo de exemplo de banco de dados chamado NorthWind, o qual iremos
utilizado para manipulação de dados.
Ao iniciar o Access aparecerá a seguinte tela:
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 30
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Clique na opção "Abrir banco de dados existentes", selecione o arquivo Northwind e clique em "OK".
Caso o arquivo não esteja na relacionado na lista de arquivos, selecione a opção "Mais arquivos..." e em
seguida o botão OK. O arquivo encontra-se na seguinte pasta "C:\Arquivos de Programas\Microsoft
Office\Exemplos".
Após o arquivo aberto aparecerá a seguinte tela:
Esta janela possui toda estrutura do arquivo Nortwind, esta estrutura é dividida pelas seguintes guias:
Tabela / Consulta / Formulário / Relatórios / Macros / Módulos, a guia tabela possui todas as tabelas do
Northwind, que utilizaremos nos nossos exercícios.
Clique na guia Consulta, exclua todas as consultas existentes nesta caixa ( Shift+Delete).
A caixa deverá ficar com a seguinte aparência:
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 31
SQL - Structure Query Language
ESCOLA TÉCNICA DE INFORMÁTICA
Clique no botão NOVO, em seguida na aparecerá a seguinte tela:
Selecione a opção Modo estrutura e clique no botão OK.
Em seguida clique no botão Cancelar na próxima Caixa de Diálogo.
Pronto! Você deverá esta com a janela de consulta aberta. (observe a figura abaixo)
Antes de iniciarmos os nossos exercícios, precisaremos alterar para a janela MODO SQL.
Siga as seguintes instruções:
Clique no Menu Exibir, opção Modo SQL.
Esta janela será utilizada para criarmos nossas consultas através da SQL. Para executar cada consulta
clique no botão "Executar" na barra de ferramentas.
Obs1.: Para cada consulta criada utilizaremos um arquivo, ou seja, gravaremos a consulta atual e
abriremos uma nova.
Obs2.: Caso necessário consulte os anexos de tabelas para resolução dos exercícios.
Luis Fernando Calábria/Erick Franklin/Leonardo Bandeira
Página 32