apostilasql-cefet(rj)

25
1 CEFET/RJ Projeto de Banco de Dados Prof. Jorge Soares A Linguagem de Consulta Estruturada (SQL Structured Query Language) n 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 procedural (linguagens de 4 a 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. o Comentários Temos duas formas diferentes de comentar consultas SQL: 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: SELECT nome_func -- Estamos selecionando o campo “nome_funcFROM Funcionário -- da tabela de funcionários WHERE idade >= 25 -- que tenham pelo menos 25 anos de idade

Upload: euaepn

Post on 13-Jun-2015

343 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: apostilaSQL-CEFET(RJ)

1

CEFET/RJ Projeto de Banco de Dados Prof. Jorge Soares

A Linguagem de Consulta Estruturada (SQL − Structured Query Language)

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 procedural (linguagens de 4a 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

Temos duas formas diferentes de comentar consultas SQL:

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:

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

Page 2: apostilaSQL-CEFET(RJ)

2

A Linguagem de Manipulação de Dados da SQL

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.

Quatro comandos integram esta classe:

• SELECT – Seleção de atributos de uma tabela

• INSERT – Inclusão de uma ou várias tuplas em uma tabela

• DELETE – Remoção de uma ou várias tuplas de uma tabela

• UPDATE – Atualização de valores de atributos

Seguem-se as especificações de cada um dos comandos DML da SQL:

O comando SELECT

Formato Geral:

SELECT [ALL | DISTINCT] lista-de-seleção FROM tabela [nome-correlato] [ , tabela [nome-correlato] ] [ WHERE condição ] [ GROUP BY atributo [ , atributo ] ] [ HAVING condição ] [ ORDER BY atributo [ , atributo ] [ASC | DESC] ]

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

Page 3: apostilaSQL-CEFET(RJ)

3

FUNCIONÁRIO

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

10712 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

11345 Marcelo Vasconcelos NULL NULL 7321

DIVISÃO

cod_divisao sig_divisao nome_divisao mat_diretor depto

7105 DIMED Divisão de Assistência Médica, Odontológica e Social 10377 7100

7321 DIDAP Divisão de Desenvolvimento de Aplicações 11057 7300

7322 DISUT Divisão de Suporte Técnico 10258 7300

7323 DISOP Divisão de Suporte Operacional 10713 7300

DEPARTAMENTO

cod_dep sig_depto nome_depto mat_diretor mat_assessor

7100 RH Departamento de Recursos Humanos 10922 NULL

7300 INF Departamento de Informática 10490 11345

Page 4: apostilaSQL-CEFET(RJ)

4

As consultas a seguir terão os as tabelas abaixo como resultados (classificação segundo Date [1]):

(a) Consulta simples com recuperação de alguns campos:

SELECT matricula, nome_func FROM Funcionário

/* Mostre o número da matrícula e o nome de todos os funcionários */

matricula nome_func

10223 Carlos Henrique Oliveira

10258 Marcelo Faria Espíndola

10377 Adelci Moura Lima

10490 Renato Braga Gadelha

10713 Aldenir Machado Flores

10902 Alberto Mello de Cima

10922 Leonardo Sartori Filho

11057 Roberto Fernandes Gomes

11344 Jorge de Abreu Soares

11345 Marcelo Vasconcelos

(b) Especificação de rótulos para dados de saída:

SELECT ‘Nome do Funcionário: ‘, nome_func FROM Funcionário

/* Mostre o nome de todos os funcionários */

col1 nome_func

Nome do Funcionário: Carlos Henrique Oliveira

Nome do Funcionário: Marcelo Faria Espíndola

Nome do Funcionário: Adelci Moura Lima

Nome do Funcionário: Renato Braga Gadelha

Nome do Funcionário: Aldenir Machado Flores

Nome do Funcionário: Alberto Mello de Cima

Nome do Funcionário: Leonardo Sartori Filho

Nome do Funcionário: Roberto Fernandes Gomes

Nome do Funcionário: Jorge de Abreu Soares

Nome do Funcionário: Marcelo Vasconcelos

(c) Uso do qualificador ALL:

SELECT ALL depto FROM Divisao

/* Mostre o código das departamentos responsáveis por divisões */

depto

7100

7300

7300

7300

(d) Uso do qualificador DISTINCT:

SELECT DISTINCT depto FROM Divisao

/* Mostre sem repetições o código das departamentos responsáveis por divisões */

depto

7100

7300

Page 5: apostilaSQL-CEFET(RJ)

5

(e) Consulta simples com qualificação:

SELECT matricula, nome_func, endereco, salario FROM Funcionário WHERE matricula < 11000

/* 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 endereco salario

10223 Carlos Henrique Oliveira Av. Marques de Sapucaí,40 14.875,22

10258 Marcelo Faria Espíndola Alameda Final, 1000 79.500,00

10377 Adelci Moura Lima Av. Rio Branco, 09 63.000,00

10490 Renato Braga Gadelha R. das Acácias, 60 80.000,00

10713 Aldenir Machado Flores Tr. Mário Filho, 60 78.000,00

10902 Alberto Mello de Cima Av. Marques de Sapucaí,40 8.574,45

10922 Leonardo Sartori Filho R. Miguel Couto, 23 25.880,01

(f) Consulta simples com ordenação padrão:

SELECT matricula, nome_func FROM Funcionário WHERE matricula >= 11000 ORDER BY nome_func

/* Mostre o número da matrícula e o nome de todos os funcionários que possuam matrícula maior ou igual a 11000, em ordem crescente de nome do funcionário */

matricula nome_func

11344 Jorge de Abreu Soares

11345 Marcelo Vasconcelos

11057 Roberto Fernandes Gomes

(g) Consulta simples com ordenação decrescente:

SELECT matricula, nome_func FROM Funcionário WHERE matricula >= 11000 ORDER BY nome_func DESC

/* Mostre o número da matrícula e o nome de todos os funcionários com matrícula maior ou igual a 11000, em ordem decrescente do nome do funcionário */

Page 6: apostilaSQL-CEFET(RJ)

6

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)

(h) Consulta de junção com igualdade simples:

SELECT cod_dep, Departamento.nome_depto FROM Departamento, Divisao WHERE (depto = cod_dep) AND (sig_divisao = ‘DIDAP’)

/* Mostre o código e o nome das departamentos que tenham uma divisão com nome ‘DIDAP’ */

cod_dep nome_depto

7300 Departamento de Informática

(i) Consulta de junção com desigualdade simples:

SELECT cod_dep, Departamento.nome_depto FROM Departamento, Divisao WHERE (depto = cod_dep) AND (sig_divisao <> ‘DISOP’)

/* Mostre o código e o nome das departamentos que não tenham uma divisão com nome ‘DISOP’ */

cod_dep nome_depto

7100 Departamento de Recursos Humanos

(j) Consulta de junção de uma tabela com ela mesma:

SELECT f1.matricula AS O_que_ganha_mais, f2. matricula AS O_que_ganha_menos FROM Funcionário f1, Funcionário f2 WHERE f1.cod_lotacao = f2.cod_lotacao AND f1.salario > f2.salario AND f1.cod_lotacao = 7321

Page 7: apostilaSQL-CEFET(RJ)

7

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

(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’ */

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

10490 Renato Braga Gadelha Rua do Acre, 80 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

11345 Marcelo Vasconcelos NULL NULL 7321

A cláusula UNION

Efetua a união lógica do resultado de duas consultas.

Formato Geral:

consulta1 UNION consulta2

O resultado das consultas 1 e 2 devem ser compatíveis, ou seja, os atributos retornados pelas consultas devem ser os mesmos.

Page 8: apostilaSQL-CEFET(RJ)

8

Exemplo:

( SELECT matricula, nome_func, endereco FROM Funcionário WHERE endereco LIKE ‘Av.%’ )

UNION

( SELECT matricula, nome_func, endereco FROM Funcionário WHERE matricula > 11000 )

/* Mostre o número da matrícula, o nome e o endereço dos funcionários que tenham endereço iniciando com o padrão ‘Av.’ ou com o número da matrícula menor que 11000 */

tem como resultado:

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:

SELECT cod_lotacao, count(*) AS total_funcionarios FROM Funcionário GROUP BY cod_lotacao

/* Mostre o número da divisão e o seu respectivo número total de funcionários lotados */

e resultaria:

cod_lotação total_funcionarios

7105 1

7300 1

7321 4

7322 2

7323 2

Page 9: apostilaSQL-CEFET(RJ)

9

Se quiséssemos melhorar o aspecto 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:

( SELECT sig_divisao, nome_divisao, count(*) AS total_funcionarios FROM Funcionário, Divisao WHERE cod_lotacao = cod_divisao -- Junção das tabelas “Divisão” e “Funcionário” GROUP BY sig_divisao, nome_divisao )

UNION

( SELECT sig_depto, nome_depto, count(*) AS total_funcionarios FROM Funcionário, Departamento WHERE cod_lotacao = cod_dep GROUP BY sig_depto, nome_depto )

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

sig_divisao nome_divisao total_funcionarios

DIDAP Divisão de Desenvolvimento de Aplicações 4

DIMED Divisão de Assistência Médica, Odontológica e Social 1

DISOP Divisão de Suporte Operacional 2

DISUT Divisão de Suporte Técnico 2

INF Departamento de Informática 1

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

Page 10: apostilaSQL-CEFET(RJ)

10

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.

matricula nome_func endereco salario cod_lotacao

10713 Aldenir Machado Flores Tr. Mário Filho, 60 78000,00 7323

10902 Alberto Mello de Cima Av. Marquês de Sapucaí, 40 8574,45 7323

10922 Leonardo Sartori Filho R. Miguel Couto, 23 25880,01 7322

11057 Roberto Fernandes Gomes Av. Barão de Ladário, 50 45500,00 7321

11344 Jorge de Abreu Soares R. Uruguaiana, 50 500,00 7321

11345 Marcelo Vasconcelos NULL NULL 7321

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.

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:

SELECT sig_divisao, nome_divisao, count(*) AS total_funcionarios FROM Funcionário, Divisao WHERE cod_lotacao = cod_divisao -- Junção das tabelas “Divisao” e “Funcionário” GROUP BY sig_divisao, nome_divisao

que tem como resultado:

sig_divisao nome_divisao total_funcionarios

DIDAP Divisão de Desenvolvimento de Aplicações 4

DIMED Divisão de Assistência Médica, Odontológica e Social 1

DISOP Divisão de Suporte Operacional 2

DISUT Divisão de Suporte Técnico 2

Se tivéssemos imposto uma restrição aos grupos, através da cláusula HAVING, a consulta seria:

SELECT sig_divisao, nome_divisao, count(*) AS total_funcionarios FROM Funcionário, Divisao WHERE cod_lotacao = cod_divisao -- Junção das tabelas “Divisao” e “Funcionário” GROUP BY sig_divisao, nome_divisao HAVING count(*) > 1

/* 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, se o número de funcionários destas divisões for maior que 1 */

sig_divisao nome_divisao total_funcionarios

DIDAP Divisão de Desenvolvimento de Aplicações 4

DISUT Divisão de Suporte Técnico 2

DISOP Divisão de Suporte Operacional 2

Page 11: apostilaSQL-CEFET(RJ)

11

Predicados

Especificam um relacionamento entre duas expressões:

expressão1 predicado expressão2 Operadores de comparação válidos:

• [not] like

• [not] between

• [not] in

• all | any | some

• [not] exists

• is [not] NULL

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.

Formato Geral:

expressão [NOT] LIKE padrão [ESCAPE caracter_de_escape ]

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

retornaria como resultado:

matricula nome_func endereco salario cod_lotacao

10223 Carlos Henrique Oliveira Av. Marques de Sapucaí,40 14.875,22 7321

10713 Aldenir Machado Flores Tr. Mário Filho, 60 78.000,00 7323

Se a cláusula ESCAPE for especificada, 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:

Page 12: apostilaSQL-CEFET(RJ)

12

SELECT * FROM Funcionário WHERE nome_func LIKE ‘%\[A-F\]ima’ ESCAPE ‘\’

/* Mostre todos os dados dos funcionários que tenham nome terminando com o padrão ‘Aima’, ‘Bima’, ‘Cima’, ‘Dima’, ‘Eima’ ou ‘Fima’ */

retornaria como resultado:

matricula nome_func endereco salario cod_lotacao

10902 Alberto Mello de Cima Av. Marques de Sapucaí,40 8.574,45 7323

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

SELECT * FROM Funcionário WHERE nome_func LIKE ‘%[A-F]ima’

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

Ou seja, a condição acima é verdadeira se e somente se x < y e y < z.

Exemplos:

SELECT * FROM Funcionário WHERE matricula BETWEEN 10500 AND 11000

/* Mostre todos os dados dos funcionários que tenham número de matrícula entre 10500 e 11000 */

matricula nome_func endereco salario cod_lotacao

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

Page 13: apostilaSQL-CEFET(RJ)

13

e o resultado da consulta:

SELECT * FROM Funcionário WHERE matricula NOT BETWEEN 10500 AND 11000

/* Mostre todos os dados dos funcionários que não tenham número de matrícula entre 10500 e 11000 */

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:

Não se pode utilizar subconsultas neste predicado.

3. O predicado IS NULL

Formato Geral:

expressão IS [NOT] NULL

Esta sentença é verdadeira se o valor retornado por expressão for nulo (ou não for nulo, quando NOT é especificado).

Exemplos:

SELECT * FROM Funcionário WHERE endereco IS NULL

/* Mostre todos os dados dos funcionários que tenham um endereço nulo */

tem como resultado:

matricula nome_func endereco salario cod_lotacao

11345 Marcelo Vasconcelos NULL NULL 7321 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:

Page 14: apostilaSQL-CEFET(RJ)

14

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

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:

matricula nome_func endereco salario cod_lotacao

11057 Roberto Fernandes Gomes Av. Barão de Ladário, 50 45.500,00 7321

e SELECT cod_divisao, nome_divisao FROM Divisao WHERE cod_divisao IN ( SELECT cod_lotacao FROM Funcionário WHERE salario < 1000 )

/* Mostre o código e o nome estendido da divisão que tenha um funcionário com salário menor que R$ 1000,00 */

retorna:

cod_divisao nome_divisao

7321 Divisão de Desenvolvimento de Aplicações

Page 15: apostilaSQL-CEFET(RJ)

15

5. O predicado EXISTS

Formato Geral:

[NOT] EXISTS (subconsulta)

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:

SELECT cod_dep, sig_depto, nome_depto, mat_diretor FROM Departamento WHERE EXISTS ( SELECT * FROM Divisao WHERE sig_divisao = ‘DIMED’) /* Exiba todos os dados das departamentos, se por acaso existir alguma divisão de nome ‘DIMED’ */

exibiria:

cod_dep sig_depto nome_depto mat_diretor

7100 RH Departamento de Recursos Humanos 10922

7300 INF Departamento de Informática 10490

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”

• Não é mandatória a especificação da subconsulta com o caracter *. 6. O predicado ANY-OR-ALL

Formato Geral:

operador-any-or-all (subconsulta)

Page 16: apostilaSQL-CEFET(RJ)

16

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.

Os operadores any-or-all podem ser:

= ANY (equivalente ao IN)

<> ANY (ou != ANY)

< ANY

<= ANY

> ANY

>= ANY

= SOME (equivalente ao IN)

<> SOME (ou != SOME)

< SOME

<= SOME

> SOME

>= SOME

= ALL

<> ALL(ou != ALL)

< ALL

<= ALL

> ALL

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

SELECT * FROM Funcionário WHERE matricula < ALL ( SELECT matricula

FROM Funcionário WHERE matricula >= 10500 )

/* Mostre todos os dados dos funcionários com número de matrícula menor que 10500 */

devolve:

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

Page 17: apostilaSQL-CEFET(RJ)

17

O comando INSERT

Temos dois formatos possíveis:

INSERT INTO tabela [ ( nome-do atributo [ , nome-do atributo ] ) ] VALUES ( valor-constante [ , valor-constante ] )

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:

1. INSERT INTO Funcionário VALUES ( 10250, ‘Alberto Mello’, ‘Rua do Acre, 80’, 5100.00, 7322)

insere o registro acima com todos os campos preenchidos na tabela de Empregados.

2. Já a sentença

INSERT INTO Funcionário ( matricula, nome_func, cod_lotacao ) VALUES ( 11344, ‘Jorge de Abreu Soares’, 7321)

insere o registro acima na tabela de Funcionários, com o campo “endereco” desconhecido (nulo).

3. As sentenças

CREATE TABLE Temporaria ( sig_depto VARCHAR(50), nome_func SMALLINT );

INSERT INTO Temporaria SELECT sig_depto, count(Divisao.*) FROM Departamento, Divisão WHERE (cod_dep = depto) GROUP BY sig_depto

armazena na tabela “Temporária“, o nome de cada departamento e o número de diretores das suas divisões subordinadas..

Esta tabela pode ser removida posteriormente com o comando:

DROP TABLE Temporaria

/* Remova do banco de dados a tabela ‘Temporaria’ */

O comando DELETE

Formato Geral:

DELETE FROM tabela [WHERE condição]

Page 18: apostilaSQL-CEFET(RJ)

18

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

DELETE FROM Funcionário WHERE nome_func = ‘João da Silva’

removeria todos os Funcionários que tivessem o nome “João da Silva”.

2. Já a sentença

DELETE FROM Funcionário

removeria todos os Funcionários da tabela “Funcionário”.

3. DELETE FROM Funcionário WHERE matricula = ( SELECT matricula FROM Funcionário, Divisão WHERE cod_lotacao = cod_divisao AND Divisão.sig_divisao = ‘DISOP’ )

/* Remova todos os registros de funcionários que trabalhem na divisão de nome ‘DISOP’ */

removeria todas as tuplas de funcionários da DISOP.

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:

nome-da-função ( [DISTINCT | ALL] nome-da-função )

Page 19: apostilaSQL-CEFET(RJ)

19

onde nome-da-função pode assumir os seguintes valores:

Nome da função Tipo do valor de retorno Descrição

count Inteiro Determina o número de instâncias de um atributo

sum Inteiro, Real Soma os valores das instâncias de um atributo

avg Real Determina o valor da média (sum/count) dos valores constantes em um atributo

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

• Valor padrão ALL (todas as ocorrências, mesmo as duplicadas, são retornadas).

• Valores nulos são ignorados por funções agregadas, exceto a função “count“.

A função agregada “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

• Com o caracter “*”, não podemos utilizar os qualificadores ALL ou DISTINCT

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

Consulta Valor Retornado

SELECT sum(Funcionário.salario) FROM Funcionário

/* Mostre a soma dos salarios de todos os funcionários */ 395.829,68

SELECT count(*) FROM Funcionário WHERE cod_lotacao = 7323 /* Mostre o número de funcionários lotados na divisão/departamento de número 7323 */

2

SELECT count(*) FROM Funcionário WHERE cod_lotacao = 7321 /* Mostre o número de funcionários lotados na divisão/departamento de código 7321 */

4

SELECT avg(Funcionário.salario) FROM Funcionário WHERE cod_lotacao = 7321 /* Mostre a média salarial dos funcionários lotados na divisão/departamento de número 7321 */

20.291,74

Page 20: apostilaSQL-CEFET(RJ)

20

SELECT max(Funcionário.salario) FROM Funcionário /* Mostre o valor máximo de salário percebido por um funcionário */

80.000,00

SELECT min(Funcionário.matricula) FROM Funcionário /* Mostre a menor matrícula de funcionário */

10223

Note que, na 3a consulta, o 6o 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.

Separadores de Sentenças

• Para separar duas sentenças SQL, usa-se o caracter ’;’

• A última sentença não necessita do separador

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

• Só podem existir até 30 correlações em uma consulta

• 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

Page 21: apostilaSQL-CEFET(RJ)

21

• Não se pode usar nomes de tabelas existentes como correlatas para outras tabelas.

Exemplo:

Suponha que, além da tabela de Funcionários, possuíssemos a tabela de Localidades (endereço completo do Funcionário) e de Cidades. A seguinte consulta conteria um erro sintático:

SELECT func.nome_func FROM Funcioná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:

SELECT nome_func, cod_lotacao FROM Funcionário, Divisão WHERE ( cod_lotacao = ( SELECT cod_divisao FROM Divisão, Departamento WHERE (depto = cod_dep) AND (sig_depto = ‘INF’) ) OR ( cod_lotacao = ( SELECT cod_divisao

FROM Funcionário WHERE (nome_func = ‘José da Silva’) )

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

• 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 */

Os atributos sig_divisao da sentença sig_divisao = ‘DIDAP’ e o atributo matricula da sentença matricula > 200 serão buscados na relação Divisão. O atributo sig_divisao será encontrado na tabela

Page 22: apostilaSQL-CEFET(RJ)

22

de divisões, mas matricula não pertence a nenhuma delas. Portanto, a análise da consulta sobe um nível de cláusula FROM, buscando e encontrando o atributo matricula na relação Funcionário.

A Linguagem de Definição de Dados da SQL

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.

Três comandos integram esta classe:

• CREATE [TABLE | VIEW | INDEX] – Criação de uma tabela (CREATE 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 (DROP TABLE), de uma visão (DROP VIEW) ou de um índice (DROP INDEX).

Especificaremos em detalhes cada um deles.

Observações:

• Considere os itens envoltos em colchetes como opcionais.

• Nos exemplos a seguir, utilizaremos as tabelas:

FUNCIONÁRIO(matricula, nome_func, endereco, salario, cod_lotacao)

DIVISÃO(cod_divisao, sig_divisao, nome_divisao, mat_diretor, cod_dep_respon)

DEPARTAMENTO (cod_dep, sig_depto, nome_depto, mat_diretor, mat_assessor)

O comando CREATE TABLE

Formato Geral:

CREATE TABLE nome-da-tabela ( definição-da-coluna [ , definição-da-coluna ] )

e definição-da-coluna é definida como:

nome-da-coluna tipo-de-dado [NOT NULL]

Exemplo: A sentença

CREATE TABLE Funcionário ( matricula SMALLINT NOT NULL, nome_func CHAR(30), endereco VARCHAR(50), salario DECIMAL, cod_lotacao SMALLINT NOT NULL ) PRIMARY KEY (matricula)

cria a tabela

FUNCIONÁRIO(matricula, nome_func, endereco, salario, cod_lotacao);

Page 23: apostilaSQL-CEFET(RJ)

23

e a obrigatoriedade de valores não nulos nos campos matricula e cod_lotacao.

O comando CREATE VIEW

Formato Geral:

CREATE VIEW nome-da-visão [ ( nome-do atributo [ , nome-do atributo ] ) ] AS sub-consulta

Exemplo:

CREATE VIEW Func_Info ( mat, nomef ) AS SELECT matricula, nome_func FROM Funcionário, Divisão WHERE (cod_lotacao = cod_divisao) AND (sig_divisao = ‘DIDAP’)

/* 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’ */

SELECT nomef

FROM Func_Info

WHERE nomef LIKE “%SILVA” AND mat > 50

O comando CREATE INDEX

Formato Geral:

CREATE [UNIQUE] INDEX nome-do-índice ON nome-do-tabela

( nome-do atributo [ , ordem ] [ , [ nome-do atributo [ , ordem ] ] ) [ CLUSTER ]

onde ordem pode assumir os valores ASC (ascendente – valor padrão) ou DESC (descendente) para o armazenamento do índice para um certo atributo.

Este é um comando normalmente utilizado paras definir chaves secundárias.

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:

Page 24: apostilaSQL-CEFET(RJ)

24

CREATE UNIQUE INDEX ind_func ON Funcionário (nome_func)

/* Crie um índice único para cada atributo nome_func da tabela Funcionário */

O comando ALTER TABLE

Formato Geral:

ALTER TABLE nome-da-tabela ADD [CONSTRAINT nome-da-restrição] cláusula-de-restrição | DROP CONSTRAINT nome-da-restrição | ADD [COLUMN] nome-do-atributo tipo-de-dado [cláusula default]

[cláusula nula] [restrição-da-coluna] | DROP [COLUMN] nome-do-atributo RESTRICT | CASCADE

Exemplo: A sentença

ALTER TABLE Funcionário ADD COLUMN telefone varchar(15)

transforma a tabela de Funcionários em:

FUNCIONÁRIO(matricula, nome_func, endereco, salario, cod_lotacao, telefone)

Obs.: Não disponível no CA-OpenIngres com esta funcionalidade

O comando DROP TABLE

Formato Geral:

DROP TABLE nome-da-tabela

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.

Exemplo DROP TABLE Funcionário /* Remova do banco de dados a tabela “Funcionário” */

O comando DROP INDEX

Formato Geral:

DROP INDEX nome-do-índice

Esta sentença remove a descrição do índice do catálogo do banco.

Exemplo: DROP INDEX ind-func /* Remova do banco de dados o índice “ind-func” */

O comando DROP VIEW

Formato Geral:

Page 25: apostilaSQL-CEFET(RJ)

25

DROP VIEW nome-da-visão

Remoção da visão especificada, bem como todas as visões definidas a partir da especificada.

Exemplo:

DROP VIEW Funcionários_Informatica /* Remova do banco de dados a visão “Funcionários_Informatica” */

O comando COMMENT

Usado para tecer e armazenar comentários sobre objetos do banco de dados.

Formatos Gerais:

COMMENT ON TABLE nome-da-tabela IS string-de-comentário

COMMENT ON COLUMN nome-da-coluna IS string-de-comentário

Exemplos:

COMMENT ON TABLE Funcionário IS ‘Tabela de Alocação de Funcionários’ /* Adicione a string ‘Tabela de Alocação de Funcionários’ como comentário à tabela “Funcionário” */

COMMENT ON COLUMN Funcionário.nome_func IS ‘Nome completo do funcionário’

/* Adicione a string ‘Nome completo do Funcionário’ como comentário à coluna “nome_func” da tabela “Funcionário” */

Referências Bibliográficas

[1] C. J. Date; Introdução a Sistemas de Bancos de Dados; Ed. Campus, 1991

[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