Linguagem SQL

Propaganda
07 – Linguagem SQL
SI1 - 07
1
Etapas do processo
Levantamento dos requisitos
Requisitos
Estudo do modelo Entidade Associação
Concepção do Modelo Entidade Associação
Estudo do modelo Relacional
Modelo Entidade Associação
Concepção do Modelo Relacional
Modelo Relacional
Estudo da Normalização
Normalização do Modelo Relacional
Modelo Relacional Normalizado
Estudo da LDD -SQL
Construção do modelo físico para um SGBD
Estudo da álgebra relacional
Estudo da LMD -SQL
Desenho físico e implementação
SI1 - 07 de Dados
Utilização da Bases
2
O que é / como usar o SQL ?

SQL (Structured Query Language) é uma linguagem normalizada,
utilizada nos SGBD para realizar acções de:






Interrogação
Manipulação de Dados
Definição de Dados
Controlo de Transações
Autorizações e Segurança
Na maioria dos SGBD Relacionais, o SQL pode ser utilizado:


Interactivamente
Embutido em Linguagens de Programação

existem diversas extensões em que os comandos SQL podem ser
embutidos em linguagem de programação tradicionais (C, C++, etc).
SGBD – Sistemas de Gestão de Bases de Dados
SI1 - 07
3
Componentes da linguagem SQL

LDD - Linguagem de Definição de Dados


do inglês DDL - “Data Definition Language”
Permite:


construir o Esquema da base de dados
LMD - Linguagem de Manipulação de Dados


do inglês DML - “Data Manipulation Language”
Permite:




aceder à informação armazenada na base de dados
inserir nova informação na base de dados
eliminar informação na base de dados
alterar informação na base de dados
SI1 - 07
4
Características da linguagem SQL

Unifica a LDD e a LMD numa única linguagem

Inclui aspectos relacionados com a administração da base de
dados

É um standard da ISO e da ANSI

É uma Linguagem não-Procedimental


Existe uma clara abstracção perante a estrutura física dos dados



Especifica-se O QUÊ e não COMO
não é necessário especificar caminhos de acesso
não é necessário elaborar algoritmos de pesquisa física
As operações efectuam-se sobre:


conjuntos de Dados (Tabelas)
não é necessário (nem possível) manipular os Dados Linha-a-Linha.
SI1 - 07
5
Perspectiva Histórica


1970: “Codd” define o Modelo Relacional
1974: IBM desenvolve o SYSTEM/R com a linguagem SEQUEL


Lançamento de SGBDs comerciais




(Structured English Query Language) cujo nome depois evoluiu para SQL
1979: Primeiro SGDB comercial (ORACLE)
1981: SGBD INGRES
1983: IBM anuncia o DB2
Normas SQL




1986, 1987: Norma SQL-87 (ANSI X3.135-1986 e ISO 9075:1987)
1989: Norma SQL-89 (ANSI X3.135.1-1989)
1992: Norma SQL-92 ou SQL2 (ISO/IEC 9075:1992)
1999: Norma SQL:1999 ou SQL3


2003: Norma SQL:2003


Added regular expression matching, recursive queries, triggers, support for procedural
and control-of-flow statements, non-scalar types, and some object-oriented features.
Introduced XML-related features, window functions, standardized sequences, and columns with
auto-generated values
2006: Norma SQL:2006

ISO/IEC 9075-14:2006 defines ways in which SQL can be used in conjunction with XML. It
defines ways of importing and storing XML data in an SQL database, manipulating it within the
database and publishing both XML and conventional SQL-data in XML form. In addition, it
provides facilities that permit applications to integrate into their SQL code the use of XQuery, to
concurrently access ordinary SQL-data and XML documents.
SI1 - 07
6
SQL - Alguns comandos principais

Definição de Dados


Manipulação de Dados


SELECT. Usado para interrogar a BD.
Controlo de Transações


INSERT, UPDATE, DELETE. Usados para inserir novos registos em
tabelas, alterar ou eliminar registos já existentes.
Interrogação


CREATE, ALTER, DROP. Usados para criar, alterar ou eliminar
qualquer estrutura de dados (tabelas, vistas e índices).
COMMIT, ROLLBACK. Usados para controlar explicitamente as
transacções.
Autorizações e Segurança

GRANT, REVOKE. Usados para atribuir ou retirar direitos de acesso.
SI1 - 07
7
Operações Relacionais

Operadores Unários



Operadores Binários







Restrição
Projecção
União
Intersecção
Diferença
Produto Cartesiano
Junção
Divisão agregação
Operação Relacional

consiste na aplicação de um Operador Relacional a um conjunto de
uma ou mais relações e tem como resultado uma nova relação.
SI1 - 07
8
Definição de dados
criar, alterar, apagar tabelas
DDL – Linguagem de Definição de Dados
SI1 - 07
9
Definição do Esquema da Base de Dados

Comandos SQL pertencentes à Linguagem de Definição de Dados
(LDD):



CREATE, para criar uma tabela
ALTER,
para alterar uma tabela existente
DROP,
para eliminar uma tabela a existente

Uma tabela pode ser criada em qualquer momento de uma sessão SQL
A estrutura de uma tabela pode ser alterada em qualquer momento de
uma sessão SQL
Toda a informação eliminada não pode ser recuperada

Uma tabela não tem qualquer dimensão predeterminada


SI1 - 07
10
Tipos de Dados

O Standard SQL2:







BIT( n ), BIT VARYING( n )
CHARACTER( n ), CHARACTER VARYING( n )
DATE, TIME, TIMESTAMP
DECIMAL, NUMERIC
FLOAT, REAL, DOUBLE PRECISION
INTEGER, SMALLINT
No caso do SQL Server:






Booleano: BIT
Binários: BINARY[(n)], VARBINARY[(n)]
Caracter: CHAR[(n)], VARCHAR[(n)]
Data e Hora: DATETIME, SMALLDATETIME (ao milissegundo, ao minuto)
Numérico aproximado: FLOAT[(n)], REAL (n bits of mantissa (1-53), default 53,
real = float(24)
Numérico exacto:



Decimal: DECIMAL[(p[,s])], NUMERIC[(p[,s])] (numeric = decimal)
Inteiro: BIGINT, INT, SMALLINT, TINYINT (respectivamente 8, 4, 2 e1 bytes)
Monetário: MONEY, SMALLMONEY (respectivamente 8 e 4 bytes)*
* Ambos com precisão de 1/10000 da unidade
SI1 - 07
11
Tipos de Dados

No caso do MySQL:






Binários: BIT[(n)]
Caracter: CHAR[(n)], VARCHAR[(n)], ENUM, TEXT
Data e Hora: DATE, DATETIME, TIME, YEAR, TIMESTAMP
Numérico exacto: DECIMAL[(p[,s])], NUMERIC [(p[,s])],
Numérico aproximado: FLOAT[(n, d)], DOUBLE[(m, d)]
Inteiro: BIGINT, INT, MEDIUMINT, SMALLINT, TINYINT
MEDIUMINT - 3 bytes
SI1 - 07
12
Tipos de Dados (cont.)

Algumas características de tipos de dados (no caso de SQL Server):

Para os tipos de dados VAR...(n) apenas é alocado o espaço necessário
para guardar o dado, até ao máximo definido (n), que pode ter o valor de
max (231-1 bytes/caracteres ).

Para o correspondente tipo sem o prefixo VAR, é alocado todo o espaço
definido (n), independentemente da dimensão efectiva do dado.


Pelo facto de ocupar um espaço fixo, o acesso ao tipo VAR... pode ser mais rápido
do que ao correspondente tipo sem o prefixo VAR
É de utilizar o tipo VAR quando se prevê, nessa coluna, existência de valores
nulos ou grandes variações na dimensão dos dados

BINARY(n), n grupos de 2 dígitos hexadecimais, para guardar dados binários

DATETIME, data e hora (8bytes), com resolução ao milissegundo (3.33 ms) *

SMALLDATETIME, data e hora (4bytes), com resolução ao minuto *
* desde 1/1/1900
SI1 - 07
13
Tipos de Dados (cont. 1)

Algumas características de tipos de dados (no caso de SQL Server):


DECIMAL e NUMERIC são idênticos e existem ambos por razões de
compatibilidade.
DECIMAL[(p[,s])] - o parâmetro “p” (precision) indica o número máximo total
de dígitos; o parâmetro “s” (scale) indica o número máximo de dígitos à
direita do ponto decimal.



No SQL Server precision pode ir de 1 a 38, com valor por omissão de 18. Scale
por ir até 0 a precision, sendo o valor por omissão de 0.
Espaço ocupado: varia em função de precision/p, sendo 5 se p  [1 – 9], 9 se p 
[10-19], 13 se p  [20-28] e 17 se p  [29-38].
FLOAT[(n)] – n indica o número de bits para guardar a mantissa.


No SQL server, o n pode variar entre 1 e 53, sendo 53 o seu valor por omissão,
mas o seu valor é tido como 24 se for inferior ou igual a 24, e 53 se for superior a
24. O espaço ocupado é de 4 bytes para n = 24 e 8 bytes para n = 53, tendo
respectivamente uma precisão de 7 e 15 dígitos.
O tipo REAL, corresponde a FLOAT(24)
SI1 - 07
14
Criação de uma tabela

Comando CREATE
CREATE TABLE nome_tabela (
nome_coluna tipo [restrição_coluna], ...
[restrição_tabela, …]
[AS SELECT comando]
)

Exemplo de criar uma tabela com algumas colunas
CREATE TABLE ITEMFACTURA (
numFactura int,
numLinha int,
produto varchar(30),
quantidade int NOT NULL DEFAULT ‘1’
)
NOT NULL, indica que a coluna não pode receber o valor NULL
DEFAULT ‘1’, indica que o valor por omissão é 1
SI1 - 07
15
Criação de uma tabela - restrições

restrição_coluna (aplica-se apenas a uma coluna)

restrição_tabela (aplica-se a uma ou mais colunas)

Definição de uma restrição:
CONSTRAINT nome_restrição
[PRIMARY KEY | UNIQUE] ( coluna, … ) |
[FOREIGN KEY ( coluna, … ) {REFERENCES tabela [( coluna, … )]
[ON DELETE {NO ACTION | CASCADE | SET DEFAULT | SET NULL} ] |
[ON UPDATE {NO ACTION | CASCADE | SET DEFAULT | SET NULL} ] } |
[CHECK ( condição )]

ON DELETE/UPDATE: NOACTION, CASCADE, SET DEFAULT, SET NULL
Remoção de um tuplo que tenha tuplos a referencia-lo, por intermédio de uma chave estrangeiras,
resulta em:
ON DELETE NOACTION→ a acção de DELETE não é realizada
ON DELETE CASCADE→ na remoção/alteração desses tuplos
ON DELETE SET DEFAULT→ na colocação das referências com o valor por omissão
ON DELETE SET NULL → na colocar dessas referências a NULL
SI1 - 07
16
Criação de uma tabela – exemplos

Definição de uma tabela com uma chave primária, uma chave
candidata (alternativa) e restrição de valor NULL por CHECK:
CREATE TABLE ALUNO (
numAluno int CONSTRAINT pk_ALUNO PRIMARY KEY,
numBI char(8) NOT NULL CONSTRAINT ak1_ALUNO UNIQUE,
nome varchar(100),
CONSTRAINT ck1_ALUNO CHECK ( nome IS NOT NULL )
)

Definição de uma tabela com chave primária composta:
CREATE TABLE ITEMFACTURA (
numFactura int,
numLinha int,
produto varchar(50) not null,
quantidade int not null,
CONSTRAINT pk_ITEMFACTURA PRIMARY KEY ( numFactura,
numLinha )
)
SI1 - 07
17
Criação de uma tabela – exemplos

Definição de uma tabela com chave estrangeira composta:
CREATE TABLE ENTREGA (
numEntrega int,
dataEntrega datetime NOT NULL,
numFactura int NOT NULL,
numLinha int NOT NULL,
CONSTRAINT pk_ENTREGA PRIMARY KEY ( numEntrega ),
CONSTRAINT fk1_ENTREGA_ITEMFACTURA
FOREIGN KEY ( numFactura, numLinha )
REFERENCES ITEMFACTURA ( numFactura, numLinha )
ON DELETE CASCADE
)
*
Considere-se que cada item de factura pode ser entregue separadamente.
Não será o caso normal.

ON DELETE CASCADE indica que,


a remoção de uma linha da tabela FACTURA ,
implica a remoção das linhas da tabela ENTREGA que lhe estiverem associadas
* Quando a FK referencia uma PK não é necessário declarar os atributos da PK (no SQL Server)
SI1 - 07
18
Criação de uma tabela – exemplos

Definição de uma tabela com uma regra de verificação (CHECK):
CREATE TABLE ENCOMENDA (
numEnc int CONSTRAINT pk_ENCOMENDA PRIMARY KEY,
dataEnc datetime NOT NULL,
codCliente int NOT NULL CONSTRAINT fk1_ENCOMENDA_CLIENTE
FOREIGN KEY REFERENCES CLIENTE (codCliente),
dataEntrega datetime,
CONSTRAINT ck1_ENCOMENDA CHECK ( dataEntrega > dataEnc )
)

Definição de uma tabela com valores seleccionados de outra tabela:
CREATE TABLE EMPREGADO_AUX (
(codigoEmpregado, nomeEmpregado, codigoCategoria)
AS SELECT codEmp, nome, codCat FROM EMPREGADO
)
1.
2.
Cria a tabela Empregado_aux com as colunas codigoEmpregado, nomeEmpregado e
codigoCategoria, que irão ter domínios idênticos respectivamente às colunas codEmp,
nome e codCat da tabela Empregado.
A tabela Empregado_aux é preenchida com o resultado do select, ou seja com todos os
empregados.
No SQL Server: select codDep, nomeDep into departamento_aux from departamento where ...;
SI1 - 07
19
Alterações a uma tabela

Comando ALTER
ALTER TABLE nome_tabela
[ ADD novas colunas | novas restrições_coluna ]
[ MODIFY definição das colunas ]
[ DROP coluna | restrição_coluna ]

Algumas alterações possíveis:





acrescentar colunas, eventualmente acompanhadas de restrições
acrescentar restrições de integridade à tabela
modificar o tipo de determinada coluna
remover uma restrição da tabela
É uma boa política criar as tabelas e depois adicionar as chaves estrangeiras
com ALTER, pois fica independente da ordem pela qual as tabelas são
criadas. Exemplo:
Alter table INSCRICAO add constraint fk_inscricao_aluno
foreign key (numAluno) references ALUNO
SI1 - 07
20
Alterações a uma tabela (cont. 1)

Algumas limitações às alterações:


Não se pode modificar uma coluna com valores NULL para NOT NULL.
Só se pode adicionar uma coluna NOT NULL a uma tabela que não contenha
nenhuma linha.



solução: adicionar a coluna como NULL, preenche-la completamente e depois
mudar para NOT NULL
Pode-se decrementar o tamanho de uma coluna e o tipo de dados, caso
essa coluna tenha valor NULL em todas as linhas.
Exemplos de alterações:
ALTER TABLE EMPREGADO
ADD comissao int NOT NULL;
ALTER TABLE DEPARTAMENTO
MODIFY nome varchar( 50 ) NOT NULL;
SI1 - 07
21
Alterações a uma tabela (cont. 2)

Exemplos de alterações:
Eliminar uma coluna:
ALTER TABLE EMPREGADO
DROP comissao

Eliminar uma restrição de integridade:
ALTER TABLE ENCOMENDA
DROP CONSTRAINT ck1_ENCOMENDA

Acrescentar uma restrição de integridade (chave estrangeira):
ALTER TABLE ENCOMENDA
ADD CONSTRAINT fk1_ENCOMENDA_cliente
FOREIGN KEY codCliente
REFERENCES CLIENTE ( codCliente )

SI1 - 07
22
Remoção de uma tabela

Comando DROP
DROP TABLE nome_tabela

Exemplo de remoção da tabela EMPREGADO
DROP TABLE EMPREGADO

Algumas características da acção de remoção de uma tabela:



a remoção de uma tabela causa a perda de todos os dados nela existentes,
assim como de todos os índices associado
Uma tabela, assim como uma qualquer entidade, só pode ser removida caso
não haja nenhuma dependência sobre ela
uma tabela só pode ser removida por quem tenha permissões para tal
SI1 - 07
23
Colunas auto-incrementáveis ( Identity )

Identity
 permite declarar uma coluna com valores autoincrementáveis,
 pode-se definir o valor inicial (valor da esquerda) e o passo
do incremento (valor da direita)
CREATE TABLE new_employees (
id int IDENTITY(1,1),
firstname varchar (20),
lastname varchar(30)
);
INSERT new_employees (firstname, lastname)
VALUES ('Karin', 'Josephs');
-- ficará com id = 1
INSERT new_employees (firstname, lastname)
VALUES ('Pirkko', 'Koskitalo');
-- ficará com id = 2
(verificar se é standard)
Extra / Não standard
SI1 - 07
24
Constraint Unique (Chaves candidatas)

Constraint Unique




Permite declarar que um conjunto de colunas tem de ter sempre
valores únicos. Tal permite declarar chaves alternativas.
Cria um índex com valores únicos, o que permite acelerar as pesquisas
que utilizem as colunas existentes no índex.
Pode-se aplicar UNIQUE na definição de uma coluna, ou aplicar como
uma restrição (constraint) de uma tabela.
Exemplo:
create table hotel (
designacao varchar(30),
regiao varchar(20) not null,
codHotel int IDENTITY(1,1),
preco decimal(8,2) not null,
data_inauguracao smalldatetime not null,
constraint pk_hotel primary key (designacao, regiao),
constraint ak_hotel unique (codHotel)
);
SI1 - 07
25
UniqueIdentifier

UniqueIdentifier – tipo identificador único

É um tipo de identificador global e único: 16-byte GUID com a forma
textual de: ‘xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx’
CREATE TABLE MyUniqueTable (
UniqueColumn UNIQUEIDENTIFIER DEFAULT NEWID(),
Characters VARCHAR(10)
)
GO
INSERT INTO MyUniqueTable(Characters) VALUES ('abc')
INSERT INTO MyUniqueTable VALUES (NEWID(), 'def')
GO
Extra / Não standard
SI1 - 07
26
Colunas computadas (computed columns)

Colunas computadas



São colunas virtuais, que não são fisicamente existentes na tabela, mas
que existem como resultado da aplicação e uma expressão aplicada às
restantes colunas da mesma tabela
Uma coluna computada pode ficar fisicamente registada caso se assinale
como PERSISTED.
Exemplo:
CREATE TABLE FACTURA (
numFactura int,
numLinha int,
produto varchar(50) not null,
quantidade int not null,
custoUnitario decimal(18,2) not null,
custo AS custoUnitario * quantidade,
CONSTRAINT pk_FACTURA PRIMARY KEY ( numFactura, numLinha )
)
SI1 - 07
27
Manipulação de dados
inserir, alterar, remover linhas
SI1 - 07
28
Manipulação de Dados

Comandos SQL pertencentes à Linguagem de Manipulação de Dados
(LMD):

INSERT - insere novas linhas numa tabela
INSERT INTO <nome da tabela> [(coluna1, coluna2, ...)]
VALUES (valor1, valor2, ...)
[comando SELECT]

UPDATE - actualiza linhas de uma tabela
UPDATE <nome da tabela>
SET coluna=valor | expressão, coluna=valor | expressão, ...
[WHERE <condição>]

DELETE - remove linhas de uma tabela
DELETE FROM <nome da tabela>
[WHERE <condição>]
SI1 - 07
29
Inserção de linhas numa tabela


Inserção directa de dados
Pretende-se registar a existência do departamento de Marketing,
localizado em Lisboa e com código 4
INSERT INTO DEPARTAMENTO ( codDep, nome, localizacao )
VALUES( 4, 'Marketing', 'Lisboa’ )

Características do comando INSERT (aplicado deste modo):




apenas se pode inserir uma linha de cada vez *
pode-se omitir a lista de nomes de colunas, desde que se respeite a ordem
das colunas definidas na tabela e não se omita nenhum valor
pode-se inserir uma linha apenas com algumas das colunas da tabela,
ficando os campos omitidos com valores nulos
É boa política indicar os nomes das colunas, pois fica-se com independência
face a alterações na definição da tabela
Multirow inserts, since SQL-92 (DB2, MySQL, H2, PostgreSQL)
INSERT INTO table (column1, [column2, ... ])
VALUES (value1a, [value1b, ...]) [, (value2a, [value2b, ...]) ] *
Exemplo:
INSERT INTO phone_book VALUES ('John Doe', '555-1212'), ('Peter Doe', '555-2323');
SI1 - 07
30
Insert MultiRow no SQL Server
Uma forma de se conseguir um insert multi-linha, quando tal não existe, é fazer
a junção dos dados através do comando UNION
insert into aeronave
(codAeronave, fabricanteAeronave, modeloAeronave, autonomia)
select 'AIRBUS-A580', 'AIRBUS', 'A580', '5000' union all
select 'AIRBUS-A480', 'AIRBUS', 'A480', '4000' union all
select 'AIRBUS-A380', 'AIRBUS', 'A380', '3000' union all
select 'BOIENG-747' , 'BOIENG', '747' , '5500';
SI1 - 07
31
Inserção de linhas numa tabela (cont.)

Inserção com dados provenientes de uma tabela

Pretende-se copiar para a tabela Empregado_Lisboa os empregados da
tabela Empregado com localização de ‘Lisboa’:
INSERT INTO EMPREGADO_LISBOA( codEmp, nome )
SELECT E.codEmp, E.nome
FROM EMPREGADO AS E
WHERE E.localizacao = ‘Lisboa’ *

Características do comando INSERT (aplicado deste modo):

o número de colunas na lista da cláusula SELECT tem que ser igual ao
número de colunas referidas no comando INSERT e os domínios de colunas
correspondentes têm que ser compatíveis
* O comando SELECT será descrito mais à frente
SI1 - 07
32
Actualização de linhas numa tabela

Pretende-se registar o facto do empregado com código 123 ter mudado
de departamento e de chefe. O seu novo departamento tem código 444
e o seu novo chefe tem código 654
UPDATE EMPREGADO
SET codDep = 444, codEmpChefe = 654
WHERE codEmp = 123

Características do comando UPDATE:



A acção de update será aplicada às linhas da tabela EMPREGADO que
verifiquem a cláusula WHERE
se a cláusula WHERE for omitida, todas as linhas da tabela são actualizadas
os valores a actualizar podem ser o resultado de expressões ou
interrogações (SELECT) à Base de Dados
SI1 - 07
33
Remoção de linhas numa tabela

Pretende-se remover os empregados do departamento 222
DELETE FROM EMPREGADO
WHERE codDep = 222

Características do comando DELETE:


se a cláusula WHERE for omitida, todas as linhas da tabela são removidas
Pretende-se remover toda a informação relativa ao histórico dos
empregados
DELETE FROM HISTORICO_EMPREGADO
SI1 - 07
34
Interrogação de dados
Comando Select
LMD - Linguagem de Manipulação de Dados
Select …
from …
where …
SI1 - 07
35
Interrogação à Base de Dados

Começando pela interrogação da Base de Dados, a sintaxe geral de
uma questão SQL é a seguinte:
SELECT [DISTINCT] <colunas> | *
FROM <tabelas>
[WHERE <condição>]

Onde





<colunas> especifica a lista de atributos cujos valores interessa conhecer
<tabelas> especifica quais as tabelas envolvidas no processamento da
interrogação
<condição> traduz a expressão lógica que define a condição a verificar
DISTINCT é aplicado a todas as colunas especificadas na cláusula SELECT
e elimina as repetições existentes
O símbolo * é utilizado quando se pretendem seleccionar todos os atributos
da tabela especificada na cláusula FROM
SI1 - 07
36
Projecção
EMPREGADO
codEmp
nomeEmp
1
António Abreu
2
Bernardo Bento
3
Carlos Castro
4
Manuel Matos

dataAdmissao
01-Jan-99
01-Jan-99
01-Jan-99
7-Feb-90
codCat
1
1
3
3
codDept
1
2
3
2
codEmpChefe
1
1
1
2
Qual o código e nome de cada empregado ?

 codEmp, nomeEmp (EMPREGADO)
SELECT codEmp, nomeEmp
FROM EMPREGADO
resultado
codEmp
1
2
3
4
nomeEmp
António Abreu
Bernardo Bento
Carlos Castro
Manuel Matos
SI1 - 07
37
Projecção (select distinct)
EMPREGADO
codEmp
nomeEmp
1
António Abreu
2
Bernardo Bento
3
Carlos Castro
4
Manuel Matos

dataAdmissao
01-Jan-99
01-Jan-99
01-Jan-99
7-Feb-90
codCat
1
1
3
3
codDept
1
2
3
2
Quais as datas de admissão e código de categoria dos
empregados?

 dataAdmissao, codCat (EMPREGADO)
resultado
dataAdmissao
01-Jan-99
01-Jan-99
01-Jan-99
7-Feb-90
SELECT dataAdmissao, codCat
FROM EMPREGADO

codEmpChefe
1
1
1
2
codCat
1
1
3
3
DISTINCT - garante que não existem tuplos duplicados
resultado
SELECT DISTINCT dataAdmissao, codCat
FROM EMPREGADO
SI1 - 07
dataAdmissao
01-Jan-99
01-Jan-99
7-Feb-90
codCat
1
3
3
38
Selecção ou Restrição

codCat
1
2
3
designacao
CategoriaA
CategoriaB
CategoriaC
salarioBase
300
250
160
Quais as categorias cujo salário base é superior a 250 ?

 salarioBase > 250 ( CATEGORIA )
SELECT *
FROM CATEGORIA
WHERE salarioBase > 250

CATEGORIA
Operadores:
=, <, <=, >, >=, <>
OR, AND, NOT
codCat
1
designacao
CategoriaA
salarioBase
300
Pretende-se, não só informação das categorias designadas por
‘CategoriaA’, mas também das que têm salário base inferior a 200

 designacao = ‘CategoriaA’  salarioBase < 200 ( CATEGORIA )
codCat
1
3
designacao
CategoriaA
CategoriaC
salarioBase
300
160
SELECT *
FROM CATEGORIA
WHERE designacao = ‘CategoriaA’ OR salarioBase < 200
SI1 - 07
39
Composição de operações de Restrição e Projecção
EMPREGADO
codEmp
nomeEmp
1
António Abreu
2
Bernardo Bento
3
Carlos Castro
4
Manuel Matos

dataAdmissao
01-Jan-99
01-Jan-99
01-Jan-99
7-Feb-90
codCat
1
1
3
3
codDept
1
2
3
2
codEmpChefe
1
1
1
2
Qual o nome e data de admissão dos empregados da categoria com
código 3, admitidos antes do dia 1 de Janeiro de 1998 ?

 nomeEmp, dataAdmissao (  codCat = 3  dataAdmissao < ‘01/01/1998’ ( EMPREGADO ) )
SELECT DISTINCT nomeEmp, dataAdmissao
FROM EMPREGADO
WHERE codCat = 3 AND dataAdmissao < ‘01/01/1998’

nomeEmp
Manuel Matos
dataAdmissao
7-Feb-90
Quais os nomes dos empregados que são chefes deles próprios?

 nomeEmp (  codEmp = codEmpChefe ( EMPREGADO ) )
SELECT DISTINCT nomeEmp
FROM EMPREGADO
WHERE codEmp = codEmpChefe
SI1 - 07
nomeEmp
António Abreu
40
União

Considere-se o seguinte Esquema Relacional



CLIENTE( nome, morada, telefone )
FORNECEDOR( nome, morada, telefone )
Qual o conjunto que tem todos os clientes e todos os fornecedores ?

CLIENTE  FORNECEDOR
SELECT *
FROM CLIENTE
UNION
SELECT *
FROM FORNECEDOR


UNION - garante que não existem tuplos duplicados
UNION ALL - inclui todos os tuplos com eventuais duplicados
SI1 - 07
41
União (cont.)

A fim de fazer os convites para a festa de Natal em Lisboa, pretende-se
a lista com todos os nome e telefones de todos os empregados e
somente dos fornecedores de Lisboa, existentes nas tabelas
EMPREGADO e FORNECEDOR
EMPREGADO
codEmp
1
2
3
4
SELECT nome, telefone
FROM EMPREGADO
UNION ALL
SELECT nomeForn, telefone
FROM FORNECEDOR
WHERE localidade = ‘Lisboa’
nome
António Abreu
Bernardo Bento
Carlos Castro
Manuel Matos
Fornecedor
nomeForn
Continentix
Jumbix
Feira Novix
Pingo Docix
nome
telefone
Continentix
Jumbix
António Abreu
Bernardo Bento
Carlos Castro
Manuel Matos
222111333
222222111
212555666
212777888
212555444
212333111
SI1 - 07
telefone
222111333
222222111
222333444
222555111
telefone
212555666
212777888
212555444
212333111
localidade
Lisboa
Lisboa
Porto
Porto
42
Intersecção e Diferença

Quais os clientes que são também fornecedores ?
CLIENTE  FORNECEDOR
SELECT *
FROM CLIENTE
INTERSECT
SELECT *
FROM FORNECEDOR


Quais os clientes que não são fornecedores ?
CLIENTE - FORNECEDOR
SELECT *
FROM CLIENTE
EXCEPT (ou MINUS em versões anteriores à SQL.92)
SELECT *
FROM FORNECEDOR

SI1 - 07
43
União, Intersecção e Diferença

Estas operações só podem ser aplicadas se os seus operandos
(Relações) forem “Compatíveis em União”

Duas Relações R e S são Compatíveis em União se:


tiverem o mesmo Grau (número de Atributos)
a cada Atributo em R corresponder outro em S com Domínio para o qual
exista uma conversão implícita. A conversão típica é,



cadeias de caracteres convertidas na que tiver maior dimensão
tipos numéricos convertidos no que tiver maior precisão
Exemplo em que as Relação não são Compatíveis em União

CLIENTE  ( nome ( FORNECEDOR ) )
SELECT * FROM CLIENTE
UNION
SELECT nome FROM FORNECEDOR
SI1 - 07
44
Produto Cartesiano
FORNECE
codFornecedor
1
2
2
3

MATERIAL
numeroMaterial
001
002
codMaterial
001
001
002
002
Pretende-se uma lista onde cada código de fornecedor e cada código de
material, apareça combinado com cada um dos materiais

FORNECE  MATERIAL
SELECT *
FROM FORNECE, MATERIAL

nome
Parafuso
Roda Dentada
Ou escrevendo de forma explicita
codFornecedor
1
1
2
2
2
2
3
3
codMaterial
001
001
001
001
002
002
002
002
numeroMaterial
001
002
001
002
001
002
001
002
nome
Parafuso
Roda Dentada
Parafuso
Roda Dentada
Parafuso
Roda Dentada
Parafuso
Roda Dentada
SELECT *
FROM FORNECE CROSS JOIN MATERIAL
SI1 - 07
45
Produto Cartesiano e Restrição


O Produto Cartesiano, por si só, tem uma utilidade limitada pois
os registos são associados sem qualquer critério
Pode ter mais interesse saber por exemplo,


Qual o material fornecido por cada fornecedor ?
 codMaterial = numeroMaterial (FORNECE  MATERIAL)
SELECT *
FROM FORNECE, MATERIAL
WHERE codMaterial = numeroMaterial

O interesse prático da aplicação da operação de Restrição sobre
a Relação resultante de um Produto Cartesiano,

levou à definição da operação de Junção (Join)
SI1 - 07
46
Junção

Qual o material fornecido por cada fornecedor ?

FORNECE
codMaterial = numeroMaterial
MATERIAL
SELECT *
FROM FORNECE INNER JOIN MATERIAL
ON ( codMaterial = numeroMaterial )
codFornecedor
1
2
2
3

codMaterial
001
001
002
002
numeroMaterial
001
001
002
002
nome
Parafuso
Parafuso
Roda Dentada
Roda Dentada
A sintaxe geral de uma Junção é a seguinte:
… FROM <tabela1> [NATURAL] [<tipoJunção>] JOIN <tabela2>
[ON <condição>] ...


<tipoJunção> ::= INNER | <junçãoExterna> [OUTER]
<junçãoExterna> ::= LEFT | RIGHT | FULL
Inner join implicito -> SELECT * FROM FORNECE, MATERIAL WHERE codMaterial = numeroMaterial
Inner join explicito -> SELECT * FROM FORNECE INNER JOIN MATERIAL ON ( codMaterial = numeroMaterial )
SI1 - 07
47
Ambiguidade na identificação dos Atributos

Pode existir ambiguidade nas operações quando,


A ambiguidade é eliminada com a qualificação do Atributo,


colocando o nome da Relação como prefixo do nome do Atributo
Considere-se o seguinte Esquema Relacional



dois (ou mais) Atributos têm o mesmo nome em Relações diferentes
FORNECE( codFornecedor, codMaterial )
MATERIAL( codMaterial , nome )
Qual o código e nome dos materiais fornecidos por cada fornecedor?

 3, 4, 1 ( FORNECE
2=1
MATERIAL )
SELECT FORNECE.codMaterial, nome, codFornecedor
FROM FORNECE, MATERIAL
WHERE FORNECE.codMaterial = MATERIAL.codMaterial
SI1 - 07
48
Ambiguidade na identificação dos Atributos (cont.)

Pode também existir ambiguidade nas operações quando,


a mesma Relação é referida mais do que uma vez numa operação
a Relação na cláusula FROM é o resultado de um SELECT

A ambiguidade é eliminada atribuindo um pseudónimo à Relação

Considere-se o seguinte Esquema Relacional


EMPREGADO( numBI, primNome, ultNome, numBIChefe )
Para cada empregado, pretende-se saber o seu primeiro e último nome
e também o primeiro e último nome do seu chefe.

 2, 3, 6, 7 ( EMPREGADO
4=1
EMPREGADO )
SELECT EMP.primNome, EMP.ultNome, CHEFE.primNome, CHEFE.ultNome
FROM EMPREGADO AS EMP, EMPREGADO AS CHEFE
WHERE EMP.numBIChefe = CHEFE.numBI
SI1 - 07
49
Junção, Projecção e Restrição
FORNECE
codFornecedor
1
2
2
3

MATERIAL
numeroMaterial
001
002
codMaterial
001
001
002
002
nome
Parafuso
Roda Dentada
Qual o nome dos materiais fornecidos pelo fornecedor de código 1 ?

 nome (  codFornecedor = ‘1’ (FORNECE
codMaterial = numeroMaterial
SELECT M.nome AS nomeDoMaterial
FROM FORNECE AS F INNER JOIN MATERIAL AS M
ON ( F.codMaterial = M.numeroMaterial )
MATERIAL ))
nomeDoMaterial
Parafuso
WHERE F.codFornecedor = ‘1’


Notar que também às colunas se podem atribuir pseudónimos
Por vezes os pseudónimos são usados para melhorar a legibilidade
SI1 - 07
50
Select geradores de tabelas temporárias

Um select gera uma relação, que pode ser utilizada como uma tabela
normal
SELECT F.nomeForn
FROM ( SELECT *
FROM FORNECEDOR
WHERE localidade = ‘Porto’ ) AS F
Fornecedor
nomeForn
Continentix
Jumbix
Feira Novix
Pingo Docix
telefone
222111333
222222111
222333444
222555111
localidade
Lisboa
Lisboa
Porto
Porto
F
nomeForn
Feira Novix
Pingo Docix
nomeForn
Feira Novix
Pingo Docix
SI1 - 07
telefone
222333444
222555111
localidade
Porto
Porto
51
Junção, Projecção e Restrição (cont.)

Outra solução para a questão do slide 24 agora poderia ser:

 nome ((  codFornecedor = 1 (FORNECE))
codMaterial = numeroMaterial
SELECT M.nome
FROM ( SELECT *
FROM FORNECE
WHERE codFornecedor = 1 ) AS F
INNER JOIN
MATERIAL AS M
ON ( F.codMaterial = M.numeroMaterial )

MATERIAL) )
FORNECE
codFornecedor
1
2
2
3
codMaterial
001
001
002
002
MATERIAL
numeroMaterial
001
002
nome
Parafuso
Roda Dentada
Nesta solução a operação de Restrição é efectuada antes da Junção


o conjunto de tuplos a considerar na Junção é menor do que na solução
anterior
contudo os SGBD já fazem estas optimizações de forma automática
SI1 - 07
52
Não Equi-Junção

A condição de Junção pode não impor igualdade entre duas colunas
NOTA
numAluno
111
222
111
333
222

disciplina
Economia
Inglês
Álgebra
Estatistica
Biologa
ESCALA
notaMax
9
13
15
17
20
nota
15
12
17
13
16
notaMin
0
10
14
16
18
classif
Reprovado
Suficiente
Bom
Muito Bom
Excelente
Qual a classificação (classif) do aluno 222 nas diversas disciplinas ?

 1, 2, 6 (  1 = ‘222’ ( NOTA
3 >= 2  3 <= 1
ESCALA ) )
SELECT numAluno, disciplina, classif
FROM NOTA AS N INNER JOIN ESCALA AS E
numAluno disciplina
classif
222
Inglês
Suficiente
222
Biologa
Muito Bom
ON ( N.nota BETWEEN E.notaMin AND E.notaMax )
WHERE N.numAluno = ‘222’

O operador BETWEEN é apenas uma forma simplificada de escrever

( nota >= notaMin AND nota <= notaMax )
SI1 - 07
53
Junções Múltiplas

Considere-se o seguinte Esquema Relacional




Para cada categoria, pretende-se saber qual o nome dos empregados,
salário base e respectivo nome do departamento


CATEGORIA( codCat, nomeCat, salarioBase )
DEPARTAMENTO( codDep, nomeDep, localizacao )
EMPREGADO( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe )
 2, 5, 3, 10 ((CATEGORIA
1=3
EMPREGADO)
7=1
DEPARTAMENTO)
Uma junção é um operador binário, pelo que um junção entre três
relações tem de ser resolvida com duas junções.
SELECT C.nomeCat, E.nomeEmp, C.salarioBase, D.nomeDep
FROM
( CATEGORIA AS C
INNER JOIN EMPREGADO AS E ON ( C.codCat = E.codCat ) )
INNER JOIN DEPARTAMENTO AS D ON ( E.codDep = D.codDep )
SI1 - 07
54
Junções Múltiplas (cont.)

Outro modo de escrever a mesma interrogação é:
SELECT nomeCat, nomeEmp, C.salarioBase, nomeDep
FROM CATEGORIA AS C, EMPREGADO AS E, DEPARTAMENTO AS D
WHERE C.codCat = E.codCat AND E.codDep = D.codDep

Esse comando está a indicar para se fazer o produto cartesiano entre os
dados das três tabelas e depois aplicar-se uma selecção ao resultado

No entanto um interpretador de SQL poderá construir o mesmo plano de
execução para a interrogação escrita de um ou de outro modo
É uma má prática utilizar produtos
cartesianos quando se pretendem
efectuar joins. Dificulta a leitura das
querys e potencia bugs devido a
selecções mal feitas.
SI1 - 07
55
Natural join



Uma Junção Natural (Natural Join) compara todas as colunas, que
têm o mesmo nome, nas duas tabelas
A tabela resultante apenas contém uma coluna por cada par de
colunas comparadas
Expressão relacional de uma junção natural:


CATEGORIA
EMPREGADO
Comando SQL com um natural join:
SELECT *
FROM EMPREGADO NATURAL JOIN DEPARTAMENTO

Esquema de Relação resultante

???( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe, nomeDep,
localizacao )
CATEGORIA( codCat, nomeCat, salarioBase )
DEPARTAMENTO( codDep, nomeDep, localizacao )
EMPREGADO( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe )
SI1 - 07
56
Junção Externa (Outer Join) – full
CATEGORIA( codCat, nomeCat, salarioBase )
DEPARTAMENTO( codDep, nomeDep, localizacao )
EMPREGADO( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe )

Quais os empregados e categorias existentes e para cada empregado
quais as categorias superiores à sua ?

EMPREGADO
3<1
CATEGORIA
SELECT *
FROM EMPREGADO EMP FULL OUTER JOIN CATEGORIA CAT
ON ( EMP.codCat < CAT.codCat )
De notar a omissão de AS
SI1 - 07
57
Junção Externa – left e right

Se apenas estiverem disponíveis as operação de Junção Externa à
Esquerda e à Direita, a interrogação anterior pode ser escrita,

(EMPREGADO
3<1CATEGORIA)
 (EMPREGADO
3<1CATEGORIA)
SELECT *
FROM EMPREGADO EMP LEFT OUTER JOIN CATEGORIA CAT
ON ( EMP.codCat < CAT.codCat )
UNION
SELECT *
FROM EMPREGADO EMP RIGHT OUTER JOIN CATEGORIA CAT
ON ( EMP.codCat < CAT.codCat )
SI1 - 07
58
Junção Externa – exemplo
CATEGORIA( codCat, nomeCat, salarioBase )
DEPARTAMENTO( codDep, nomeDep, localizacao )
EMPREGADO( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe )

Quais os nomes de todos departamentos existentes e para cada um
qual o código e nome dos empregados que lá trabalham ? Notar que
devem ser apresentados todos os departamentos, mesmo os que não
têm empregados.

 2, 4, 5 ( DEPARTAMENTO
1=4
EMPREGADO ) )
SELECT DEP.nomeDep, codEmp, EMP.nomeEmp
FROM DEPARTAMENTO DEP LEFT OUTER JOIN EMPREGADO EMP
ON ( DEP.codDep = EMP.codDep )
SI1 - 07
59
Funções de agregação
SI1 - 07
60
Funções de Agregação

Podem ser usadas na cláusula SELECT



MAX( <expressão> )


valor máximo da expressão, para as linhas seleccionadas. O resultado não
inclui tuplos duplicados.
MIN( <expressão> )


ou HAVING (que será posteriormente apresentada)
aplicam-se sobre um grupo de linhas, devolvendo um resultado
valor mínimo da expressão, para as linhas seleccionadas. O resultado não
inclui tuplos duplicados.
<expressão>

pode incluir operadores aritméticos: +, - ,*, / e os ()
SI1 - 07
61
Funções de Agregação (cont.)

COUNT( * )


COUNT( [DISTINCT] <coluna> )


somatório dos valores [diferentes] da expressão
AVG( [DISTINCT] <expressão> )


número de linhas excluindo as que, para a coluna indicada, têm valor NULL.
Caso se use DISTINCT não se consideram valores duplicados
SUM( [DISTINCT] <expressão> )


número total de linhas
média (SUM / COUNT) dos valores [diferentes] da expressão
SUM e AVG apenas se aplicam a valores numéricos
SI1 - 07
62
Funções de Agregação (cont. 1)
CATEGORIA( codCat, nomeCat, salarioBase )
DEPARTAMENTO( codDep, nomeDep, localizacao )
EMPREGADO( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe )

Qual o nome do empregado que aparecerá em primeiro lugar numa
ordenação lexicográfica crescente ?

 MIN nome ( EMPREGADO )
SELECT MIN( nomeEmp )
FROM EMPREGADO

Qual o total de nomes diferentes dos empregados em ‘Lisboa’ ?

 COUNT 5 ( (  localizacao = ‘Lisboa’ ( DEPARTAMENTO ) )
EMPREGADO )
SELECT COUNT( DISTINCT E.nomeEmp )
FROM DEPARTAMENTO AS D INNER JOIN EMPREGADO AS E
ON ( D.codDep = E.codDep )
WHERE localizacao = ‘Lisboa’
SI1 - 07
63
Funções de Agregação (cont. 2)

Qual o valor total dos salários base a pagar aos empregados do
departamento 1 e qual o valor de IRS (calculado a 22%)?

 SUM salarioBase, SUM (salarioBase)*0.22 (
(  codDep = 1 ( EMPREGADO ) )
3=1 CATEGORIA
)
SELECT SUM( C.salarioBase ), SUM( C.salarioBase) * 0.22 as IRS
FROM EMPREGADO as E INNER JOIN CATEGORIA as C
on ( E.codCat = C.codCat )
WHERE codDep = 1
CATEGORIA( codCat, nomeCat, salarioBase )
DEPARTAMENTO( codDep, nomeDep, localizacao )
EMPREGADO( cod_Emp, nomeEmp, codCat, codDep, codEmpChefe )
SI1 - 07
64
Sub-Interrogação (subquery)
CATEGORIA( codCat, nome, salarioBase )
DEPARTAMENTO( codDep, nome, localizacao )
EMPREGADO( cod_Emp, nome, codCat, codDep, codEmpChefe )

Qual o nome dos empregados que trabalham no mesmo departamento
que o(s) empregado(s) com nome ‘Rui Costa' ?
SELECT DISTINCT E2.nome
FROM EMPREGADO AS E1 INNER JOIN EMPREGADO AS E2
ON ( E1.codDep = E2.codDep )
WHERE E1.nome = Rui Costa’ AND E1.codEmp <> E2.codEmp

Outra solução consiste em considerar duas sub-interrogações:


Qual o código do departamento do(s) empregado(s) ‘Rui Costa' ?
Qual o nome dos empregados do departamento, com o código obtido na
interrogação anterior, mas que não são esse ‘Rui Costa’ ?
SI1 - 07
65
Sub-Interrogação (cont.)

Qual o código do departamento do(s) empregado(s) ‘Rui Costa' ?
SELECT DISTINCT E2.codDep
FROM EMPREGADO AS E2
WHERE E2.nome = ‘Rui Costa‘

Qual o nome dos empregados do(s) departamento(s) com os códigos
obtidos na interrogação anterior, mas que não são ‘Rui Costa’ ?

assumindo que existem cinco empregados com o nome ‘Rui Costa’ e que
que três deles estão no departamento 4, um está no 7 e outro no 11
SELECT DISTINCT E1.nome
FROM EMPREGADO AS E1
WHERE E1.nome <> ‘Rui Costa' AND
E1.codDep IN ( 4, 7, 11 ) *
* Operador IN (v1, v2, v3), equivale a “valor =v1 OR valor = v2 OR valor = v3”
SI1 - 07
66
Sub-Interrogação (cont. 1)

Resposta à questão inicial:


Qual o nome dos empregados que trabalham no mesmo departamento que
o(s) empregado(s) com nome 'Rui Costa' ?
Obtida através da composição das duas interrogações numa única
interrogação:
SELECT DISTINCT E1.nome
FROM EMPREGADO AS E1
WHERE E1.nome <> 'Rui Costa' AND
E1.codDep IN
( SELECT DISTINCT E2.codDep
FROM EMPREGADO AS E2
WHERE E2.nome = 'Rui Costa’ )

Sub-interrogação (interrogação interior): “(SELECT … E2.codDep ...”
SI1 - 07
67
Sub-Interrogação Não-Correlacionada

Numa Sub-Interrogação Não-Correlacionada a interrogação interior não
necessita dos valores da interrogação exterior

Quais os códigos e nomes das categorias com menor salário base ?
SELECT C.codCat, C.nome
FROM CATEGORIA AS C
WHERE C.salarioBase =
( SELECT MIN( D.salarioBase )
FROM CATEGORIA AS D )

A interrogação interior (SELECT MIN(… ) não depende da exterior


a interrogação interior é executada em primeiro lugar e apenas uma vez
a relação devolvida na interrogação interior permite resolver a exterior
SI1 - 07
68
Sub-Interrogação Correlacionada

Numa Sub-Interrogação Correlacionada a interrogação interior necessita
de valores da interrogação exterior

Quais as categorias cujo salário base é inferior a metade do valor médio
dos salários efectivos dos empregados dessas categorias ?
CATEGORIA( codCat, nome, salarioBase )
EMPREGADO( codEmp, nome, salarioEfectivo, codCat, codDep )
SELECT C.*
FROM CATEGORIA AS C
WHERE C.salarioBase <
( ( SELECT AVG( E.salarioEfectivo )
FROM EMPREGADO AS E
WHERE E.codCat = C.codCat ) / 2 )

A interrogação interior (SELECT AVG(… ) depende da exterior


a informação da interrogação exterior é passada à interior *
para cada linha da interrogação exterior é executada a interior
* Devido ao WHERE E.codCat = C.codCat, que compara com um valor da interrogação externa
SI1 - 07
69
Cláusula WHERE

Foi anteriormente apresentada a sintaxe geral de uma questão SQL
SELECT [DISTINCT] <colunas> | *
[FROM <tabelas>]
[WHERE <condição>]

<condição>


Cada “Predicado”,



consiste numa colecção de “Predicados”
pode envolver qualquer composição de sub-expressões do mesmo tipo,
combinada com os operadores lógicos AND, OR, NOT e parêntesis
Cada “Predicado”,

quando avaliado produz um valor lógico verdadeiro ou falso, para o tuplo
considerado
SI1 - 07
70
Predicados

Os Predicados podem ser utilizados num contexto estático, sendo
avaliados com base em valores constantes.


Alguns Predicados também ser avaliados com base em valores
dinâmicos, a retirar da base de dados



... WHERE E1.codDep IN ( 4, 7, 11 ) ...
… WHERE D.codDep IN ( SELECT E2.codDep FROM EMPREGADO AS E2)
neste caso é utilizada um “Sub-Interrogação” (Subquery)
As “Sub-Interrogações” podem-se usar em Predicados:




Comparação, BETWEEN
IN
ALL, ANY
EXISTS
SI1 - 07
71
Predicados (cont.)

LIKE: devolve true se a cadeia de caracteres tiver um determinado
padrão


comparação (=, <>, >, <, >=, <=) e BETWEEN



WHERE salarioBase > ANY ( SELECT … )
EXISTS (se existe pelo menos uma linha *)


WHERE codCat IN ( 1, 2 )
ANY (em pelo menos um valor *), ALL (em todos os valores *)


WHERE nomeEmp = ‘Manuel Silva’
WHERE codEmp BETWEEN 1 AND 5
IN


WHERE nomeEmp LIKE '%n%‘ (nomes com ‘n’, % = 0 ou mais caracteres)
WHERE EXISTS ( SELECT … )
Teste de valor nulo

WHERE comissao IS NULL
* da subquery
SI1 - 07
72
LIKE

Devolve true se a cadeia de caracteres tiver um determinado padrão

<expressão> [NOT] LIKE <padrão>


expressão: deve ser do tipo cadeia de caracteres (string)
padrão: pode incluir meta-caracteres, que não sendo precedidos do caracter
de excepção, têm o seguinte significado,





‘%’ qualquer sequência de zero ou mais caracteres
‘_’ um único qualquer caracter
[G-J] ou [GHIJ] qualquer caracter do intervalo (G a J, neste exemplo)
[^G-J] ou [^GHIJ] qualquer caracter não pertencente ao intervalo mencionado
Nomes de empregados que começam por “Ana”
SELECT * FROM EMPREGADO
WHERE nome LIKE ‘Ana%’



Nomes que comecem por ‘A’, ‘B’ ou ‘C’: LIKE ‘[ABC]%’ ou LIKE ‘[A-C]%’
Nomes que não contenham ‘Silva’:
NOT LIKE ‘%Silva%’
Nomes que a segunda letra não seja um ‘a’: LIKE '_[^a]%'
SI1 - 07
73
LIKE – carácter de excepção

<expressão> [NOT] LIKE <padrão> [ESCAPE <caracterExcepção>]


caracterExcepção: carácter que anula o tratamento especial dos caracteres
de controlo (já descritos)
Quais as categorias cujo primeiro caracter do nome não pertence ao
alfabeto (a A, … z Z) e que inclui um underscore (_) ?
SELECT * FROM CATEGORIA
WHERE nome LIKE ‘[^A-Za-z]%+_%’ ESCAPE ‘+’

Nomes que comecem por ‘+_’: LIKE '++_%' ESCAPE '+';
O carácter ‘_’ é precedido do carácter de escape ‘+’.
Pode-se definir um qualquer carácter de escape
SI1 - 07
74
IN

Verifica se um valor está contido numa coluna de uma tabela, ou numa
lista de valores

<construtor de linha> [NOT] IN
( {sub-interrogação | lista de expressões escalares} )

Quais as categorias dos empregados com maior salário efectivo ?
CATEGORIA( codCat, nome, salarioBase )
SELECT C.*
EMPREGADO( codEmp, nome, salarioEfectivo, codCat, codDep )
FROM CATEGORIA AS C
WHERE C.codCat IN
( SELECT E.codCat
FROM EMPREGADO AS E
WHERE E.salarioEfectivo =
( SELECT MAX( F.salarioEfectivo )
FROM EMPREGADO AS F ) )
SI1 - 07
75
IN (cont.)

Quais as categorias dos empregados com maior salário efectivo ?


sem utilizar o Predicado IN, temos outra solução,
CATEGORIA 1=4 (EMPREGADO 3=1( MAX salarioEfectivo (EMPREGADO)))
SELECT DISTINCT C.*
FROM CATEGORIA AS C INNER JOIN
(
EMPREGADO AS E INNER JOIN
( SELECT MAX( salarioEfectivo )
FROM EMPREGADO ) AS E1( salarioEfectivoMax )
ON ( E.salarioEfectivo = E1.salarioEfectivoMax )
)
ON ( C.codCat = E.codCat )
E1( salarioEfectivoMax ) → declaração do nome da tabela e da coluna
SI1 - 07
76
ANY, ALL – any exemplo

Verifica se em todas (ALL) ou algumas (ANY) linhas, da subquery, o
atributo obedece a uma expressão envolvendo operadores relacionais

<construtor de linha> <comparação> {ALL | ANY} (sub-interrogação*)

Qual o nome dos empregados cujo salário efectivo é superior ao de
alguns empregados da mesma categoria ?
SELECT E.nome
FROM EMPREGADO AS E
WHERE E.salarioEfectivo > ANY
( SELECT E1.salarioEfectivo
FROM EMPREGADO E1
WHERE E.codCat = E1.codCat )

substituindo ANY por ALL teríamos como resultado uma Relação vazia
* A sub-interrogação deve devolver uma só coluna de valores
SI1 - 07
77
ALL – exemplo

Qual o nome dos empregados cujo salário efectivo é superior ao salário
efectivo de todos os empregados dos departamentos localizados em
‘Lisboa’ ?
SELECT E.nome
FROM EMPREGADO AS E
WHERE E.salarioEfectivo > ALL
( SELECT E1.salarioEfectivo
FROM EMPREGADO AS E1 INNER JOIN DEPARTAMENTO AS D
ON ( E1.codDep = D.codDep )
WHERE D.localizacao = ’Lisboa' )

Sem utilizar o Predicado ALL, temos outra solução,

“… E.salarioEfectivo > ( SELECT MAX( E1.salarioEfectivo ) …”
DEPARTAMENTO( codDep, nomeDep, localização )
EMPREGADO( codEmp, nome, salarioEfectivo, codCat, codDep )
SI1 - 07
78
EXISTS, NOT EXISTS

Verifica a existência de, pelo menos, uma linha numa tabela

[NOT] EXISTS (sub-interrogação)

Quais os departamentos que têm pelo menos um empregado ?
SELECT D.*
FROM DEPARTAMENTO AS D
WHERE EXISTS
( SELECT *
FROM EMPREGADO AS E
WHERE E.codDep = D.codDep )

A condição do WHERE é verdadeira se,

o resultado da sub-interrogação for não vazio.
SI1 - 07
79
EXISTS (cont. 1)

Quais os departamentos que têm pelo menos um empregado ?

sem utilizar o Predicado EXISTS, temos as seguintes soluções:
select *
from departamento as d
where ( select count( * )
from empregado as e
where e.coddep = d.coddep ) > 0
select distinct d.*
from departamento as d
inner join empregado as e on ( d.coddep = e.coddep )
SI1 - 07
80
NOT EXISTS

Qual o código e nome das categorias que não têm empregados ?
select c.codcat, c. nome
from categoria as c
where not exists
( select *
from empregado as e
where c.codcat = e.codcat )

A condição do WHERE é verdadeira se,


o resultado da sub-interrogação for vazio.
Sem utilizar o Predicado NOT EXISTS, temos outra solução,

“… WHERE 0 = ( SELECT COUNT( E.codCat ) …”
SI1 - 07
81
Exists – exemplo

Quais os departamentos que têm empregados na categoria ‘1’ e na
categoria ‘3’ ?
select *
from departamento d
where exists (
select *
from empregado e1
where e1.codCat = '1' and e1.codDep = d.codDep)
and exists (
select *
from empregado e2
where e2.codCat = '3'and e2.codDep = d.codDep)
SI1 - 07
82
Exists e intersect


Quais os departamentos que têm empregados na categoria ‘1’ e na
categoria ‘3’?
Agora resolvido com o operador INTERSECT

Nota: O intersect pode ser resolvido por exists
select distinct d.*
from (departamento d inner join empregado e
on(d.codDep = e.codDep))
where e.codCat = '1'
intersect
select distinct d.*
from (departamento d inner join empregado e
on(d.codDep = e.codDep))
where e.codCat = '3'
SI1 - 07
83
Comparação ( = )

Quais as categorias com maior salário base ?
select c.codcat
from categoria as c
where c.salariobase =
( select max( c1.salariobase )
from categoria as c1 )

Qual o código e nome dos empregados com maior salário
base ?
select e.codemp, e.nome
from empregado as e
inner join categoria as c on ( e.codcat = c.codcat)
where c.salariobase =
( select max( c1.salariobase )
from categoria as c1 )
DEPARTAMENTO( codDep, nome, localizacao )
CATEGORIA( codCat, nome, salarioBase )
EMPREGADO( codEmp, nome, salarioEfectivo, codCat, codDep )
SI1 - 07
84
Comparação ( > )

Considere-se o seguinte Esquema Relacional


ALUNO( numAluno, nome, dataNascimento, localNascimento )
Pretende-se uma lista onde, para cada local indique todos os alunos
mais novos do que o mais velho que lá nasceu ?
select a1.localnascimento, a1.numaluno, a1.nome
from aluno as a1
where a1.datanascimento >
( select min( a2.datanascimento )
from aluno as a2
where a1.localnascimento = a2.localnascimento )
SI1 - 07
85
Operação de Divisão
r2
r1
CodDisc
t1r2
Há tuplos que não existem em r1 e
não deviam estar em t1, logo,
retiremo-los
t1r2-r1
numAL
CodDisc
2222
LC
numAL
CodDisc
2222
IA
5555
IA
3333
LC
LC
3333
IA
3333
IA
4444
LC
numAL
4444
SI-2
4444
IA
5555
4444
LC
numAL
5555
LC
4444
IA
2222
5555
IA
5555
SI-1
5555
LC
numAL
CodDisc
2222
SI-1
2222
LC
2222
IA
3333
Y
X
LC
IA
X
t1 = Y(r1)
t2 = Y((t1r2)-r1)
q = t1-t2
3333
numAL
4444
2222
5555
3333
Y
4444
SI1 - 07
86
Operação de Divisão
q = r1  r2
r2
r1
numAL
CodDisc
2222
SI-1
2222
LC
2222
IA
3333
LC
3333
IA
4444
SI-2
4444
LC
4444
IA
5555
SI-1
5555
LC
Y
CodDisc
numAL
LC
2222
IA
3333
Interessam-nos as projecções
em Y dos tuplos de r1 que estão
associados com todos os tuplos
de r2.
4444
X
Y
Logo: de r1 interessam-nos as
projecções em Y dos tuplos (t1)
tais que não existe nenhum
tuplo de r2 que não tenha
associação com t1 em r1
SELECT DISTINCT Y FROM r1 AS q
WHERE NOT EXISTS
SELECT * FROM r2
WHERE NOT EXISTS
SELECT * FROM r1
WHERE r1.X = r2.X AND q.Y = r1.Y
X
SI1 - 07
87
Divisão
Ou, recorrendo à lógica de 1ª ordem:
q = r1  r2 = {t : (t2)(t2  r2  (t1)(t1  r1  conc(t,t2,t1)))}
= {t : (t2)(~(t2  r2)  (t1)(t1  r1  conc(t,t2,t1)))}
= {t : ~( t2)~(~(t2  r2)  (t1)(t1  r1  conc(t,t2,t1)))}
= {t : ~( t2)(t2  r2  ~(t1)(t1  r1  conc(t,t2,t1)))}
= {t : ~( t2)(t2  r2  ~(t1)(t1  r1  t1.X=t2.X  t1.Y = t.Y))}
SELECT distinct Y from r1 as q -- q é uma projecção em Y de alguns registos de r1
WHERE NOT EXISTS (
SELECT * FROM r2
WHERE NOT EXISTS (
select * from r1
where r1.X = r2.X AND
q.Y = r1.Y
)
)
SI1 - 07
88
Operação de Divisão

Quais os códigos dos departamentos que têm empregados em todas as
categorias existentes?
EMPREGADO
codEmp
nomeEmp
1
António Abreu
2
Bernardo Bento
3
Carlos Castro
4
Manuel Matos
5
Manuel Matos

CATEGORIA
codCat
1
1
3
2
3
codDep
1
2
3
2
2
codCat
1
2
3
designacao
CategoriaA
CategoriaB
CategoriaC
salarioBase
300
250
160
O resultado desejado pode ser obtido efectuando uma operação de
divisão entre EMPREGADO e CATEGORIA

 3,4 ( EMPREGADO )   1 ( CATEGORIA )
codDep
2
SI1 - 07
89
Operação de Divisão (cont.)

Quais os códigos dos departamentos que têm empregados de todas as
categorias ?

Ou, colocando a questão de outro modo:




Quais os códigos dos departamentos para os quais,
qualquer que seja a categoria,
existe algum empregado desse departamento e dessa categoria
Ou, utilizando uma notação simbólica:
codigoDepartamento : categoria  CATEGORIA,
(  empregado :
EMPREGADO.codDep = codigoDepartamento
and EMPREGADO.codCat = CATEGORIA.codCat )

Vamos designar a expressão que, está escrita entre parêntesis, por:

p(x)
SI1 - 07
90
Operação de Divisão (cont. 1)

Sabendo que,


 x : p(x)   x :  p(x)
Tem-se,
codigoDepartamento :  categoria  CATEGORIA, (  p(x) )

Ou seja,
codigoDepartamento :  categoria  CATEGORIA,
(   empregado :
EMPREGADO.codDep = codigoDepartamento
and EMPREGADO.codCat = CATEGORIA.codCat )
Os departamentos (codDep) onde não exista uma categoria que não tenha um
empregado.
SI1 - 07
91
Operação de Divisão (cont. 2)

Pretende-se a informação completa sobre os departamentos que têm
empregados de todas as categorias ?

DEPARTAMENTO
1=1
(  3, 4 ( EMPREGADO )   1 ( CATEGORIA ) )
select d.*
from departamento d
where not exists
(select *
from categoria c
where not exists
(select *
from empregado e
where e.coddep = d.coddep and e.codcat=c.codcat ) )
Departamento onde não existe
Uma categoria que não possua
Um empregado nessa categoria e nesse departamento
SI1 - 07
92
Comando Select –
order by, group by e having
Select …
from …
where …
group by…
having …
order by …
SI1 - 07
93
Comando SELECT

A sintaxe de uma interrogação SQL inclui as seguintes cláusulas:
SELECT [DISTINCT] <colunas> | *
FROM <tabela>, ...
[WHERE <condição>]
[GROUP BY <expressão de agrupamento>]
[HAVING <condição>]
[ORDER BY <expressão de ordenação> [ASC | DESC], … ]
SI1 - 07
94
ORDER BY

Ordena a relação resultante, por ordem crescente ou decrescente de
uma ou mais expressões de ordenação

é sempre a última cláusula a ser especificada
SELECT [DISTINCT] <colunas> | *
FROM <tabela>, ...
[WHERE <condição>]
[ORDER BY <expressão de ordenação> [ASC | DESC], … ]

ASC: ordenação ascendente (ascending), valor por omissão

DESC: ordenação descendente (descending)
SI1 - 07
95
ORDER BY (cont.)

Pretende-se toda a informação da tabela de empregado, ordenada
lexicograficamente pelo nome do empregado, de modo crescente
select *
from empregado
order by nome asc

Pretende-se a mesma informação que a apresentada no exemplo
anterior, mas neste caso, os nomes repetidos devem aparecer
ordenados de forma decrescente pelo código do empregado
select *
from empregado
order by nome asc, codemp desc
SI1 - 07
96
GROUP BY

Produz uma linha de resultados por cada conjunto de linhas com o
mesmo valor da expressão de agrupamento

Permite agregar grupos de linhas e a estes aplicar funções de agregação
SELECT [DISTINCT] <colunas> | *
FROM <tabela>, ...
[WHERE <condição>]
[GROUP BY <expressão de agrupamento>]

Quando a cláusula GROUP BY está presente, a cláusula SELECT
apenas pode conter:


colunas que apareçam na cláusula GROUP BY, ou
funções de agregação aplicadas a quaisquer outras colunas
SI1 - 07
97
GROUP BY (cont.)

Para cada código de departamento qual o seu salário base mínimo ?
select E.codDep, min ( C.salarioBase ) as salarioMinimo
from empregado as E
inner join categoria as C on ( E.codCat = C.codCat )
group by E.codDep

Agrupamento/agregação múltiplo/a:


quando o critério de agregação é múltiplo, primeiro é executado a
agregação pela primeira coluna, e depois para os tuplos com o mesmo valor
dessa coluna é aplicada a agregação pela segunda coluna (e por aí fora…)
Para cada código de departamento, qual o salário efectivo mínimo praticado
para cada código de categoria ?
select E.codDep, E.codCat, min( E.salarioEfectivo ) as salariominimo
from empregado AS E
inner join categoria as C on ( E.codCat = C.codCat )
group by E.codDep, E.codCat
DEPARTAMENTO( codDep, nome, localizacao )
CATEGORIA( codCat, nome, salarioBase )
EMPREGADO(SI1
codEmp,
nome, salarioEfectivo, codCat, codDep )
- 07
98
GROUP BY (cont.)

Para cada departamento e cada categoria qual o número de empregados
select d.codDep, c.codCat, count(E.codcat) as numEmp
from (departamento D cross join categoria C)
left outer join empregado E
on (d.codDep = E.codDep and C.codCat= E.codCat)
group by d.codDep, c.codCat
order by d.codDep, c.codCat;
SI1 - 07
99
HAVING

Aplica uma ou mais condições a cada grupo de linhas especificado pela
cláusula GROUP BY


Se a cláusula GROUP BY não for utilizada, o grupo considerado é o de todas
as linhas resultantes do SELECT
A cláusula HAVING é usada para definir restrições a grupos, assim
como a cláusula WHERE é usada para definir restrições a linhas.
SELECT [DISTINCT] <colunas> | *
FROM <tabela>, ...
[WHERE <condição>]
[GROUP BY <expressão de agrupamento>]
[HAVING <condição>]

Utilização das cláusulas HAVING e WHERE


a cláusula HAVING deve sempre conter funções de agregação
a cláusula WHERE nunca contém funções de agregação
SI1 - 07
100
HAVING (cont.)

Pretende-se uma lista onde conste, para cada código de departamento
o salário base mínimo nele praticado. Apenas se pretendem os
departamentos com salário base médio superior a 50
select E.codDep, min( C.salarioBase )
from categoria AS C
inner join empregado as E on( C.codCat = E.codCat )
group by E.codDep
having avg( C.salarioBase ) > '50'
SI1 - 07
101
Exemplo clarificador de having
Qual o número de empregados dos departamentos que
têm mais do que dois empregados?
select t1.codDep, t1.numEmps
from (select E.codDep, count(*) as numEmps
from Empregado E
group by E.codDep) as t1
where t1.numEmps > '2'
select E.codDep, count(*) as numEmps
from Empregado E
group by E.codDep
having count(*) > '2';
SI1 - 07
102
WHERE, GROUP BY, HAVING e ORDER BY

Pretende-se uma lista onde conste, para cada código de departamento
o valor do menor salário efectivo pago a empregados da categoria com
código ‘C1’. Só se pretendem os departamentos para os quais esse
menor salário efectivo seja superior ao menor salário base de todas as
categorias. Os valores mais altos devem ser apresentados primeiro.
SELECT E.codDep, MIN( E.salarioEfectivo )
FROM EMPREGADO AS E
WHERE E.codCat = '1'
GROUP BY E.codDep
HAVING MIN( E.salarioEfectivo ) >
( SELECT MIN( salarioBase ) FROM CATEGORIA )
ORDER BY MIN( E.salarioEfectivo ) DESC
SI1 - 07
103
O conceito de valor NULL

O valor NULL permite lidar com situações onde, para determinado tuplo, o
valor de um atributo seja indefinido ou desconhecido.

Situações de utilização do valor NULL:




o atributo não é aplicável para determinado tuplo;
o atributo tem um valor desconhecido para determinado tuplo;
o atributo tem valor conhecido mas o valor está ausente nesse instante, ou
seja, ainda não foi registado na Base de Dados.
Características dos valores NULL:




Independente do domínio - inteiro, real, caracter, data, etc.
Não comparáveis entre si - uma expressão com um operador de comparação
será avaliada como FALSE, se algum dos seus operandos tiver o valor NULL.
Existe função (ISNULL) para substituir o valor NULL por outro valor.
Existe directiva (IS NULL) para encontrar valores NULL numa interrogação
(com colunas definidas como permitindo valores NULL).
SELECT ISNULL(codCat, 1) FROM EMPREGADO WHERE codDep = 3
SELECT * FROM EMPREGADO WHERE salarioEfectivo IS NULL;
SI1 - 07
104
Mais notas acerca do SQL Server

Aconselha-se uma vista a:

SQL Server 2005 Books Online (September 2007)



Transact-SQL Reference (Transact-SQL)
http://msdn.microsoft.com/enus/library/ms189826(SQL.90).aspx
Tópicos abordados:



Schemas
Funções
Top e Case
SI1 - 07
105
Schema – um espaço de nomes
use DB3;
create schema SC1;
create table SC1.T1 (
nome varchar(120) not null,
localidade varchar(40) not null
);
insert into SC1.T1 values ('Joaquim Lopez', 'Madrid');
select * from SC1.T1;
delete from SC1.T1;
drop table SC1.T1;
drop schema SC1;
O schema por omissão é: dbo
Um schema é um espaço de nomes que
pode conter tabelas
SI1 - 07
106
Funções ( Functions ) e Top

SQL Server 2005 Books Online (September 2007)

Functions (Transact-SQL)

http://msdn.microsoft.com/en-us/library/ms174318(SQL.90).aspx
Consultar o link para mais informações, esta lista serve apenas para alertar
para a existência de funções


day, Month, Year, getdate
lower, upper, substring
Rand, cos, tan, square, pi
current_user, isdate, isnull

TOP N – devolve as N primeiras linhas




pode ser um valor percentual
Extra / Não standard
SI1 - 07
107
Case

Case - Avalia uma lista de condições e retorna o valor associado à

expressão da condição que sucedeu
Sintaxe:
Simple CASE expression:
CASE input_expression
(WHEN when_expression THEN result_expression)+
[ ELSE else_result_expression ]
END
Searched CASE expression:
CASE
(WHEN Boolean_expression THEN result_expression)+
[ ELSE else_result_expression ]
END
SELECT ProductNumber, Name, 'Price Range' =
CASE
WHEN ListPrice = 0 THEN 'Mfg item - not for resale'
WHEN ListPrice < 50 THEN 'Under $50'
WHEN ListPrice >= 50 and ListPrice < 250 THEN 'Under $250'
WHEN ListPrice >= 250 and ListPrice < 1000 THEN 'Under $1000'
ELSE 'Over $1000'
END
FROM Product
SI1 - 07
108
Vistas (views)
SI1 - 07
109
Vistas (Views) da Base de Dados

Usando a terminologia SQL, uma Vista (normalmente referida como
View) consiste numa única tabela construída a partir de:



Características de uma Vista (View):




outras tabelas ou
outras Vistas anteriormente definidas.
Uma Vista (View) não tem dados próprios.
Os dados de uma Vista (View) são manipulados na(s) tabela(s) base que
servem de suporte a essa Vista.
Uma Vista (View) é armazenada como um comando SELECT.
Uma Vista (View) é uma tabela virtual, isto é, não tem existência física
embora apareça ao utilizador como se o tivesse, pelo que:


origina algumas limitações às operações de actualização (update);
não origina limitações às operações de interrogação (select).
SI1 - 07
110
Tipos de Vistas (Views) e sua utilidade

Tipos de Vistas (Views)

Vistas simples:



Vistas complexas:



construídas com base numa única tabela;
não contêm funções nem grupos de dados.
construídas com base em várias tabelas; ou
contêm funções ou grupos de dados.
Utilidade das Vistas (Views):




restringir o acesso à Base de Dados mostrando apenas parte dos dados;
simplificar a consulta dos dados, substituindo consultas elaboradas
envolvendo várias tabelas, por fáceis consultas sobre a Vista;
permitir que os mesmos dados sejam visualizados de diferentes maneiras
por diferentes utilizadores;
reduzir a possibilidade de incoerências (opção WITH CHECK OPTION alteração de dados através da Vista de acordo com a sua definição).
SI1 - 07
111
Criação de uma Vista – View

Comando CREATE VIEW
CREATE VIEW nome_vista
[ (nome_coluna_1, nome_coluna_2, ...) ]
AS SELECT comando [WITH CHECK OPTION]

“nome_coluna_i”:


nome da coluna usado na vista. Se não for especificado é assumido o
mesmo nome das colunas definidas na cláusula SELECT.
“AS SELECT comando” - consiste na directiva SELECT que define a
vista, podendo usar mais do que uma tabela e outras vistas. Esta
directiva tem algumas limitações:



não pode incluir as cláusulas ORDER BY
não pode incluir a instrução INTO
não pode referenciar uma tabela temporária.
SI1 - 07
112
Criação de uma Vista - View (Cont.)

Pretende-se criar uma vista que permita saber:
Para cada departamento quantos empregados existem e qual o montante
total de salários base.
CREATE VIEW INFORMACAODEPARTAMENTO
(nomeDepartamento, numEmpregados, totalSalarios)
AS SELECT D.nomeDep, COUNT(*), SUM(salarioBase)
FROM (DEPARTAMENTO AS D INNER JOIN EMPREGADO AS E
ON ( D.nomeDep = E.codDep )) inner join categoria C
on ( e.codCat = c.codcat)
GROUP BY D.nomeDep;


Esta vista é complexa: várias tabelas, funções e agregação de dados
DEPARTAMENTO( codDep, nome, localizacao )
CATEGORIA( codCat, nome, salarioBase )
EMPREGADO( codEmp, nome, salarioEfectivo, codCat, codDep )
SI1 - 07
113
Interrogação a uma Vista - View

Pretende-se, utilizando a vista INFORMACAO_DEPARTAMENTO,
saber:

Para o departamento de Informática, quantos empregados existem e qual o
montante total de salários.
SELECT numEmpregados, totalSalarios
FROM INFORMACAO_DEPARTAMENTO
WHERE nomeDepartamento = ‘Informática’

A vista não é concretizada no momento em que é criada, mas sempre
que é especificada uma interrogação sobre essa vista, permitindo obter
dados sempre actualizados.

As alterações das tabelas originais reflectem-se nas diversas vistas
dessas tabelas.
SI1 - 07
114
Remoção de uma Vista - View

Comando DROP
DROP VIEW nome_vista

Exemplo de remoção da vista INFORMACAO_DEPARTAMENTO
DROP VIEW INFORMACAO_DEPARTAMENTO

Algumas características da acção de remoção de uma vista:



a remoção de uma vista não tem qualquer influência nos dados das tabelas
que lhe serviam de base.
se existirem outras vistas que dependam da vista removida, essas vistas
deixam de ser válidas.
uma vista só pode ser removida por um utilizador com permissões para
efectuar essa operação
SI1 - 07
115
Actualização de dados através de uma Vista

Se a vista for definida sobre:




Se a vista for definida sobre:




uma única tabela e
sem funções de agregação de dados,
é uma operação simples que se traduz na actualização da tabela que lhe
serve de base.
múltiplas tabelas e
com funções de agregação de dados,
é uma operação complicada e que pode ser ambígua.
De uma forma geral, não são actualizáveis as vistas:


definidas sobre múltiplas tabelas utilizando junções (join);
que utilizam agrupamento de dados e funções de agregação.
SI1 - 07
116
Actualização de dados através de uma Vista (cont. 1)

O comando de DELETE não é permitido se a vista incluir:





O comando de UPDATE não é permitido se a vista incluir:



condições de junção (join);
funções de agrupamento;
o comando DISTINCT;
sub-interrogações correlacionadas.
qualquer das limitações do comando DELETE;
colunas definidas por expressões (tal como, salarioAno = 14 * salario).
O comando de INSERT não é permitido se a vista incluir:


qualquer das limitações do comando UPDATE;
colunas com possibilidade de ter valores NOT NULL que não tenham valores
de omissão nas tabelas base e que não estejam incluídas na vista através da
qual se pretende inserir novas colunas.
SI1 - 07
117
Actualização de dados através de uma Vista (cont. 2)

Os comandos de INSERT e UPDATE são permitidos em vistas
contendo várias tabelas base se:


o comando afectar apenas uma das tabelas que serve de base à vista;
no entanto, não é permitido num mesmo comando alterar mais do que uma
tabela.

As vistas permitem executar verificações de integridade sobre os dados
modificados através das vistas.

A opção WITH CHECK OPTION indica que os comandos de INSERT e
UPDATE executados através da vista só podem afectar registos
seleccionáveis pela vista (definidos no WHERE).
SI1 - 07
118
Verificação de Integridade em Vistas

Pretende-se criar uma vista que permita saber:


Quais os empregados que têm um salário inferior a 250000.
Também se pretende que qualquer acção de alteração sobre essa vista
apenas afecte os empregados cujo salário seja inferior a 250000.
CREATE VIEW VISTA_EMPREGADO
AS SELECT cod, nome
FROM EMPREGADO
WHERE salario < 250000
WITH CHECK OPTION

Devido ao Check Option as instruções de INSERT e UPDATE sobre a
vista têm que verificar as condições definidas na cláusula WHERE.

a operação será rejeitada no caso dos dados não verificarem essas
condições.
SI1 - 07
119
Tratamento das Vistas pelo SGBD

O comando CREATE VIEW não origina a execução do comando
SELECT a ele associado.

O comando CREATE VIEW apenas origina o armazenamento da
definição da vista (directiva SELECT) no dicionário de dados.

Ao aceder aos dados através de uma vista, o sistema:



extrai do dicionário de dados, a definição da vista;
verifica as permissões de acesso à vista;
converte a operação sobre a vista numa operação equivalente na tabela ou
tabelas que servem de base à vista.
SI1 - 07
120
Utilizadores e privilégios
LCD - Linguagem de Controlo de Dados
SI1 - 07
121
Segurança no acesso à Base de Dados

Conceder ou retirar, selectivamente aos utilizadores, acesso aos
objectos (ex. tabelas e vistas) da Base de Dados.

O acesso aos objectos da Base de Dados é controlado através de
privilégios.

Privilégio consiste no direito a executar um determinado comando SQL
ou em aceder a um objecto de outro utilizador. Alguns exemplos:






aceder à Base de Dados;
criar Bases de Dados.
criar, remover e alterar tabelas e vistas.
executar comandos de pesquisa de dados em tabelas.
inserir, remover e alterar dados em tabelas.
visualizar tabelas de outros utilizadores.
Uma base de dados é um contexto agrupador de tabelas e outras entidades.
Num SGBD temos os seguintes comando associados às bases de dados: CREATE databasename,
USE databasename, DROP databasename, ALTER databasename, SHOW databases
SI1 - 07
122
Privilégios

Informalmente identificam-se dois níveis para atribuição de privilégios à
utilização do sistema de base de dados:

Nível de utilizador

A este nível o administrador da base de dados (no SQL Server é o utilizador
sa) especifica os privilégios de cada utilizador (ou grupo de utilizadores), que
inclui:



criação de Bases de Dados - (no SQL Server o sa apenas pode conceder este
privilégio a utilizadores da base de dados master);
acesso a Bases de Dados;
criação de tabelas, vistas, regras de integridade e construção de cópias de
segurança (backup) - (no SQL Server este privilégio pode também ser concedido
pelo utilizador que criou a Base de Dados).
SI1 - 07
123
Privilégios (cont.)

Nível de objecto

A este nível o administrador da base de dados ou o utilizador que criou o
objecto (a base de dados, a tabela, a vista, etc) podem especificar os
privilégios de cada utilizador (ou grupo de utilizadores), que inclui:





remoção do objecto (*);
execução de pesquisas de dados sobre tabelas e vistas;
inserção, remoção e alteração de dados em tabelas;
execução de pesquisas e alterações de dados sobre cada uma das colunas de
cada tabela.
(*) no SQL Server a remoção da Base de Dados é um privilégio que é
automaticamente atribuído ao utilizador que criou a Base de Dados e
que não pode ser transferido para mais nenhum utilizador.
SI1 - 07
124
Administração de privilégios

Comando para conceder privilégios - GRANT (nível de utilizador)
GRANT { ALL | lista_privilégios_nível_utilizador }
TO { PUBLIC | lista_de_nomes }

ALL


“lista_ privilégios_nível_utilizador”


No SQL Server esta lista inclui as directivas CREATE DATABASE; CREATE
TABLE; CREATE VIEW; CREATE RULE; DUMP DATABASE
PUBLIC


No SQL Server apenas o utilizador sa pode utilizar esta opção porque só ele pode
conceder o privilégio CREATE DATABASE.
Concede acesso a todos os utilizadores.
“lista_de_nomes”

Especifica o nome de cada utilizador ou grupo, separados por vírgulas.
SI1 - 07
125
Administração de privilégios (cont. 1)

Comando para conceder privilégios - GRANT (nível de objecto)
GRANT { ALL | lista_ privilégios_nível_objecto }
ON nome_tabela_ou_vista [ (lista_colunas) ]
TO { PUBLIC | lista_de_nomes }

ALL


Indica que todos os privilégios aplicáveis ao objecto são concedidos
“lista_ privilégios_nível_objecto”



No SQL Server esta lista inclui as directivas SELECT, INSERT, DELETE,
UPDATE.
No SQL Server se o privilégio se referir a uma tabela inclui a directiva
REFERENCES, que dá ao utilizador a permissão de criar chaves estrangeiras sem
precisar de ter permissão de SELECT na tabela referenciada pela chave
estrangeira.
No SQL Server se o privilégio se referir a uma coluna esta lista apenas inclui as
directivas SELECT e UPDATE.
SI1 - 07
126
Administração de privilégios (cont. 2)

Comando para conceder privilégios - REVOKE (nível de utilizador)
REVOKE { ALL | lista_privilégios_nível_utilizador }
TO { PUBLIC | lista_de_nomes }

Comando para conceder privilégios - GRANT (nível de objecto)
REVOKE { ALL | lista_ privilégios_nível_objecto }
ON nome_tabela_ou_vista [ (lista_colunas) ]
TO { PUBLIC | lista_de_nomes }

As características do comando REVOKE são idênticas às do comando
GRANT, atrás apresentadas.
SI1 - 07
127
Criar um login e um user no SQL Server
-- criar um novo login e user para uma BD já existente *
-- criar um novo login
create login user20 with password = 'user20---';
-- criar um user para uma BD com o schema dbo por omissão
create user user20 for login user20 with default_schema = dbo;
-- no contexto da DB2 dar permissões ALL para o user20 (não ao login)
use db2;
grant all to user20;
grant insert, delete, update, select, alter on schema::dbo to user20;
-- pode-se verificar no management studio, no Object Explorer:
- em Security->Logins->user20 que o login user20 existe e que dentro
dele em User Mapping verificar que em DB2 ele tem o user20 associado
e com o schema dbo por omissão.
- em Databases->DB2->Security->Users->User20 em Securables as
permissões que ele tem para o Schema de nome ‘dbo’
* O utilizador corrente tem de ter permissões para as seguintes acções
SI1 - 07
128
Remover o user e o login
-- remover o user de uma BD e o login
-- seleccionar o contexto da base de dados em questão
use db2;
-- remover as permissões ao user sobre o schema dbo
revoke insert, delete, update, select, alter on schema::dbo to user20;
-- remover as permissões ao user relativos à base de dados
revoke all to user20;
-- remover o user
drop user user20;
-- remover o login
drop login user20;
SI1 - 07
129
Criar um login e user (via stored procedures)
-- Adds a new login account
exec sp_addlogin 'user20', 'user20---', 'db2';
use db2;
-- Adds a security account in the current database to the user
-- creates user 'user20' for login 'user20'
exec sp_grantdbaccess 'user20', 'user20';
-- To run a SELECT statement against any table or view in the database.
exec sp_addrolemember db_datareader, 'user20';
-- To add, delete, or change data in all user tables
exec sp_addrolemember db_datawriter, 'user20';
-- To run any Data Definition Language (DDL) command in a database.
exec sp_addrolemember db_ddladmin, 'user20';
alter user user20 with default_SCHEMA = dbo;
-- remover login e user
use db2;
exec sp_droprolemember db_datareader, 'user20';
exec sp_droprolemember db_datawriter, 'user20';
exec sp_droprolemember db_ddladmin, 'user20';
exec sp_revokedbaccess 'user20';
exec sp_droplogin 'user20';
SI1 - 07
130
Criar/remover bases de dados
-- criar uma base de dados se não existir
if not exists(
select * from sys.databases where name = 'DB7')
create database DB7;
-- Utilizar o contexto da base de dados DB7
use DB7;
-- Criar tabelas, vistas, etc
-- Executar: insert, update, delete, select,
-- remover uma base de dados
use master; -- utilizar outro contexto
drop database DB7;
Nota: para cada problema podem criar uma base de dados diferente no vosso servidor.
Claro que também podem criar a base de dados e apagá-la logo de seguida.
SI1 - 07
131
Sugestão para a estrutura dos scripts SQL
-- criar (caso não exista) a base de dados
if not exists(
select * from sys.databases where name = 'DB7')
create database DB7;
use DB7;
-- destruir (caso exista) todo o modelo físico
if exists(
select * from information_schema.tables where table_name = 't1')
drop table t1;
-- criar todo o modelo físico
create table t1(
col1 int
)
-- inserção de dados
insert into t1 (col1) values ('101');
-- utilização dos dados
select * from t1;
SI1 - 07
132
Desactivar/activar restrições
-- criar uma tabela com uma restrição de Check
create table dbo.t1( c1 int constraint ck_c1 check (c1 > 0) )
insert into dbo.t1 values(-1) -- ERRO
-- desactivar a verificação da restrição
alter table dbo.t1 nocheck constraint ck_c1
insert into dbo.t1 values(-1) – OK
Exemplo de utilização:
No caso em que uma tabela t1 tem uma
FK para outra tabela t2, e t2 tem uma FK
para t1 temos uma situação em que é
impossível inserir o primeiro valor. Neste
caso suspende-se uma FK e já se pode
inserir o primeiro valor.
-- reactivar a verificação da restrição
alter table dbo.t1 with nocheck check constraint ck_c1
-- forçar a verificação da restrição
Neste ponto a restrição fica não
verificada (untrusted)
alter table dbo.t1 with check check constraint ck_c1 – ERRO
delete dbo.t1 where c1 = -1
alter table dbo.t1 with check check constraint ck_c1 -- OK
SI1 - 07
133
Download