sql ÍndiceÁlgebra pedro ramos, dcti/iscte Àlgebra e sql pedro nogueira ramos...

52
Pedro Ramos, DCTI/ISCTE SQL Índice Álgebra Àlgebra e SQL Pedro Nogueira Ramos ([email protected]) DCTI / ISCTE

Upload: internet

Post on 18-Apr-2015

130 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Àlgebra e SQL

Pedro Nogueira Ramos

([email protected])

DCTI / ISCTE

Page 2: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Álgebra Relacional(Codd, 1972)

No Modelo relacional a informação é representada através de

relações (ou tabelas). A Álgebra Relacional é um conjunto de

operações formais que operam sobre relações. No essencial a

álgebra relacional corresponde à álgebra de conjuntos, ou seja,

é definida com base nos operadores de Intersecção, Produto

Cartesiano e União.

Page 3: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Tipos de Operações

Álgebra Relacional

Todas as operações produzem como resultado outras relações.

Tipos de operações:

Binárias (operam sobre conjuntos)UniãoProduto Cartesiano (e Join)

Unárias (operam apenas sobre um conjunto)Projecção Selecção

Relações compatíveis – mesmo grau (número de atributos) e atributos idênticos (i.e., tipos de dados compatíveis).

Page 4: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

União

Álgebra Relacional

Apenas pode ser efectuada entre relações compatíveis.

R S = {t: t R ou t S}, em que t representa um tuplo (linha)

A B C A B C A B C

a c f a j a a c f

b a g g c b b a g

d f a d f a d f a

a j a

g c b

d f a

As linhas duplicadas apenas são seleccionadas caso se indique explicitamente para não as retirar (UNION ALL)

Page 5: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Produto Cartesiano

Álgebra Relacional

CodPostal Localidade

1500 Lisboa

2100 Porto

3999 Évora

Localidade

Número Nome CodPostal

001 João 1500

013 Ana 2100

056 Luís NULL

Cliente

R X S = {t1.t2: t1 R e t2 S}

Número Nome Cliente. CodPostal

Localidade.CodPostal

Localidade

001 João 1500 1500 Lisboa

001 João 1500 2100 Porto

001 João 1500 3999 Évora

013 Ana 2100 1500 Lisboa

013 Ana 2100 2100 Porto

013 Ana 2100 3999 Évora

056 Luís NULL 1500 Lisboa

056 Luís NULL 2100 Porto

056 Luís NULL 3999 Évora

X =

Únicas linhas coerentes: Join

Page 6: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Join

Álgebra Relacional

INNER JOIN: Produto Cartesiano, em que apenas são seleccionados tuplos nos quais os valores dos atributos comuns são idênticos. Normalmente o atributo comum não é repetido.

OUTER LEFT JOIN: resultado do NATURAL JOIN união com os tuplos da relação à esquerda que não ”cruzaram” (não existe nenhum tuplo na relação à direita que tenha o mesmo valor no atributo comum) com a relação à direita.

OUTER RIGHT JOIN: resultado NATURAL JOIN união com os tuplos da relação à direita que não ”cruzaram” com a relação à esquerda.

Page 7: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Exemplos de Join

Álgebra Relacional

CodPostal Localidade

1500 Lisboa

2100 Porto

3999 Évora

Localidade

Número Nome CodPostal

001 João 1500

013 Ana 2100

056 Luís NULL

Cliente

X

Número Nome CodPostal Localidade

001 João 1500 Lisboa

013 Ana 2100 Porto

Número Nome CodPostal Localidade

001 João 1500 Lisboa

013 Ana 2100 Porto

056 Luís NULL NULL

Número Nome CodPostal Localidade

001 João 1500 Lisboa

013 Ana 2100 Porto

NULL NULL 3999 Évora

Natural Join

(Inner Join)

Outer Left Join

Outer Right Join

Page 8: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Projecção

Álgebra Relacional

Ai, Aj, … , Am (R) ={< t(Ai), t(Aj), …, t(Am) >: t R} em que

R(A1, A2, …, An) é a relação projectada;

Ai, Aj, …, Am são atributos da projecção;

i, j, …, m são inteiros compreendidos no intervalo 1 … n .

A B C

a c f

b a g

a f a

RA

a

b

a

(A) R

As linhas duplicadas apenas são removidas caso se indique explicitamente (DISTINCT)

Page 9: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Selecção

Álgebra Relacional

F (R) ={t: t R e t satisfaz F} em que

em que F é uma fórmula envolvendo atributos e operadores lógicos (devolvem verdade ou falso) como operandos.

A B C

a c f

a f a

R (A=a) R

A B C

a c f

b a g

a f a

Page 10: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Exemplos de Interrogações

Álgebra Relacional

1 ”Listar o nome e nacionalidade dos autores de nacionalidade Portuguesa e Brasileira”

nome, nacionalidade (nacionalidade =”Portuguesa” or nacionalidade =”Brasileira”

(Autor))

2 ”Listar os títulos dos livros do Gabriel Garcia Marquez”

titulo (nome Like ”Gabriel*” ((Autor X Autoria) X Livro))

3 ”Listar o nome dos autores, indicando os títulos dos seus livros”

a) nome, titulo ((Autor X Autoria) X Livro)

incorrecto, não selecciona os autores sem livros

b) nome, titulo (Autor X OUTER LEFT JOIN (Autoria X Livro)

Page 11: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SQL - Índice

Domínios e Tipos de Dados

Tabelas

Índices

DML (Data Manipulation Language)

Prepared Statements

Stored Procedures

Triggers

SELECT

Cláusula SELECT

Cláusula FROM

Joins

Cláusula WHERE

Cláusulas GROUP BY, HAVING e funções de agregação

UNION

UPDATE

DELETE

INSERT

Optimização de Querys

Views

Page 12: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Linguagem SQLNorma ANSI criada em 1986 (revista em 1989 e 1992).

A linguagem SQL tem duas vertentes: DDL (Data Definition

Language) e DML (Data Manipulation Language). Na vertente

DDL o SQL possui um conjunto de comandos para criação e

alteração de tabelas, chaves estrangeiras, regras de integridade

referencial e views. A vertente DML é uma implementação da

Álgebra Relacional, e.g., permite efectuar interrogações a uma

base de dados, bem como alterar, anular ou inserir registos em

tabelas.

Ao longo do texto será apresentado o SQL do Adaptive Server

Anywhere 6.0 da Sybase.

Page 13: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Domínios e Tipos de Dados (DDL)

SQL

Em SQL é possível especificar o domínio (tipo de dados) de um atributo. Através da cláusula DOMAIN é possível definir um domínio genérico ao qual podem ser atribuídos vários atributos. O seguinte comando define o domínio morada:

CREATE Datatype dm_morada VARCHAR(100);

Alguns Tipos de DadosTextoChar [(n)] (equivalente a Varchar (n))Long Varchar - infinitos caracteresText – eq. a Long Varchar mas admite NULL

BoleanoBit [0, 1]

Data

DateTimeTimeStamp (data e hora)

NúmeroTinyint [0 – 255]Smallint [-+ 32,767] ou UNSIGNED [0 - 65535]Integer [-+ 2,147,483,6479]Double [ grande]Decimal (inteiros[, decimais])

Page 14: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Tabelas (DDL) (I)

SQL

Comando para criar uma tabela:

CREATE TABLE nome databela ( definição das colunas, restrições de integridade)

CREATE Datatype dm_morada VARCHAR(100);

 

CREATE TABLE Cliente (

cod_cliente INTEGER NOT NULL,

bi INTEGER NOT NULL,

nome VARCHAR(100),

morada dm_morada,

CONSTRAINT prim_key PRIMARY KEY (cod_cliente),

CONSTRAINT cand_key UNIQUE (bi));

Chave alternativa

Page 15: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Tabelas (II)

SQL

CREATE TABLE Factura (

num_factura INTEGER NOT NULL,

data DATE NOT NULL,

valor DECIMAL(10,2) NOT NULL,

cod_cliente INTEGER NOT NULL,

CONSTRAINT prim_key PRIMARY KEY (num_factura),

CONSTRAINT for_key_cliente

FOREIGN KEY (cod_cliente)

REFERENCES Cliente (cod_cliente)

ON UPDATE CASCADE

ON DELETE RESTRICT);

CREATE TABLE Produto (

cod_produto INTEGER NOT NULL,

tipo CHAR(2) DEFAULT 'MP‘ CHECK (tipo IN ('MP','PA')) NOT NULL,

Designação VARCHAR(100),

CONSTRAINT prim_key PRIMARY KEY (cod_produto));

Chave Estrangeira

Valor por omissão

Restrições

Page 16: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Tabelas (III)

SQL

CREATE TABLE Item (

num_factura INTEGER NOT NULL,

num_item INTEGER CHECK (num_item between 1 and 10) NOT NULL,

quantidade INTEGER CHECK (quantidade > 0) NOT NULL,

valor DECIMAL (4,2) NOT NULL,

cod_produto INTEGER NOT NULL,

 

CONSTRAINT prim_key PRIMARY KEY (num_factura, num_item),

CONSTRAINT for_key_factura

FOREIGN KEY (num_factura)

REFERENCES Factura (num_factura)

ON UPDATE CASCADE

ON DELETE CASCADE,

CONSTRAINT for_key_produto

FOREIGN KEY (cod_produto)

REFERENCES Produto (cod_produto)

ON UPDATE CASCADE

ON DELETE RESTRICT);

Restrições

Page 17: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Tabelas (IV)

SQL

ALTER TABLE clienteADD COLUMN telefone VARCHAR (10)DROP COLUMN bi;

Comando para alterar uma tabela:ALTER TABLE nome databela alterações

Comando para alterar uma tabela:DROP TABLE nome databela

Nota: É conveniente ter um ficheiro com a definição completa da base de dados. Esse ficheiro pode ser executado sempre que seja necessário reconstruir a base de dados. O uso sistemático dos comandos ALTER e DROP TABLE pode dificultar a reconstrução da base de dados.

Page 18: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Índices

SQL

Comando para criar um índice tabela:

CREATE [UNIQUE] INDEX nome índice ON nome tabela (nome coluna [ASC | DESC])

create unique index Index_Key on Medicamentos_Receita (

Codigo ASC,

ID_Receita ASC

);

Page 19: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

DML Linguagem para Manipulação de Dados

SQL

SELECT

Cláusula SELECT

Cláusula FROM

Joins

Cláusula WHERE

Cláusulas GROUP BY, HAVING e funções de agregação

UNION

UPDATE

DELETE

INSERT

Optimização de Querys

Views

Page 20: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Comando SELECT

SQL

Um comando SQL típico para selecção de linhas obedece à seguinte estrutura (em que a cláusula SELECT corresponde à projecção, a cláusula FROM ao produto cartesiano e a cláusula WHERE à selecção):

SELECT campos a seleccionar

FROM tabelas onde constam os campos indicados em Select

WHERE expressão lógica que indica quais as linhas que pretendemos seleccionar

ORDER BY campo pelo qual a listagem virá ordenada;

SELECT Nome, Morada FROM Cliente WHERE Cod_Postal = 1300 ORDER BY Nome;

Lista o nome e morada de uma tabela de clientes, mas apenas os clientes cujo código postal seja 1300 (ordenado por nome)

Page 21: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Nota

SQL

É importante notar que qualquer comando SELECT devolve uma tabela (um conjunto de colunas e linhas).

Sempre que, no contexto da sintaxe da linguagem SQL for referida uma tabela, ela deve ser interpretada no sentido mais lato: uma tabela original (definida no esquema relacional) ou o resultado de um comando SELECT.

Page 22: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula SELECT (I)

SQL

Qualquer expressão sintacticamente válida pode ser argumento da cláusula SELECT. Por exemplo, os dois seguintes comandos são válidos:

SELECT Produto, Quantidade * Preço FROM Item; (devolve duas colunas em que a segunda corresponde ao produto das colunas quantidade e preço);

SELECT ‘teste’ FROM Item; (se a tabela item tiver 20 linhas, o comando devolve 20 vezes a palavra teste).

Podem ser atribuídos aliases (sinónimos) às colunas. Por exemplo o comando anterior poderia ser escrito da seguinte forma (permite dar um nome – Total - à segunda coluna devolvida):

SELECT Produto, Quantidade * Preço AS Total FROM Item;

Page 23: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula SELECT (II)

SQL

Caso pretendamos visualizar todos os campos de uma tabela, como alternativa a enumera-los todos, pode-se usar a constante *:

SELECT * FROM Item;

Caso pretendamos eliminar duplicados na listagem obtida, utiliza-se a cláusula DISTINCT (elimina linhas duplicadas)

SELECT DISTINCT CodPostal FROM Aluno; (devolve os códigos postais existentes)

Caso se pretenda listar dois atributos com o mesmo nome (correspondentes a duas tabelas referidas na cláusula FROM) é necessário preceder o nome do campo pelo nome da tabela de onde ele é originário.

Page 24: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula SELECT (III)

SQL

Caso pretendamos apenas visualizar algumas linhas de uma tabela:

SELECT FIRST * FROM Item;

SELECT TOP 3 * FROM Item;

Caso pretendamos armazenar o resultado em variáveis (apenas quando o comando apenas devolve uma linha)

SELECT Max(Quantidade) INTO Maximo FROM ITEM;

A cláusula INTO apenas se justifica quando o SQL é utilizado dentro de outra linguagem de programação (Java, C, Visual Basic, etc.) ou em Stored Procedures (ver mais adiante). Na cláusula INTO podem-se referir várias variáveis (o mesmo número das expressões da cláusula SELECT).

Page 25: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula FROM (I)

SQL

Na cláusula FROM indicam-se os nomes das tabelas envolvidas na interrogação, separadas por vírgulas. Quando existe mais que uma tabela o SQL executa automaticamente um produto cartesiano entre as tabelas. Por exemplo, o seguinte comando executa um produto cartesiano entre as tabelas Cliente e Localidade, devolvendo todos os campos (das duas tabelas):

SELECT * FROM Cliente, Localidade;

Caso queiramos obter um JOIN é necessário explicitar a forma como o pretendemos obter, por exemplo:

SELECT * FROM Cliente INNER JOIN Localidade;

SELECT * FROM Cliente LEFT OUTER JOIN Localidade;

Page 26: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula FROM (II)

SQL

Á semelhança dos sinónimos dos atributos, é possível atribuir aliases às tabelas (os sinónimos nas tabelas são relevantes nas subquerys, analisadas mais adiante):

Select * From Cliente AS Cliente_Empresa;

Existe uma tabela de sistema que apenas contém uma linha denominada DUMMY. Ela pode ser utilizada quando pretendemos listar uma expressão que não é obtida a partir de nenhuma tabela.

SELECT COS(1) FROM DUMMY;Devolve o cosseno de 1

Page 27: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – JOINS (I)

SQL

Tipos de JOINS

Key Join SELECT * FROM Cliente KEY JOIN Localidade;

Critério: chave estrangeira. Apenas funciona se existir uma (e apenas uma) chave estrangeira a ligar as duas tabelas.

Natural Join SELECT * FROM Cliente NATURAL JOIN Localidade;

Critério: atributos com o mesmo nome. Apenas funciona se existir pelo menos um atributo com o mesmo nome e tipo de dados compatíveis.

Join com ComparaçõesSELECT * FROM Cliente JOIN Localidade ON Cliente.Cod_Postal = Localidade.Cod_Postal;

Critério: indicado explicitamente no comando através do ON. É o mais flexível.

Page 28: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – JOINS (II)

SQL

INNER, LEFT OUTER e RIGHT OUTER JOIN

Podem ser utilizados nos Key, Natural e ON Join. Quando nada é indicado é efectuado um INNER Join.

SELECT * FROM Cliente NATURAL INNER JOIN Localidade;

SELECT * FROM Cliente NATURAL LEFT OUTER JOIN Localidade;

SELECT * FROM Cliente KEY RIGHT OUTER JOIN Localidade;

SELECT * FROM Cliente LEFT OUTER JOIN Localidade

ON Cliente.Cod_Postal = Localidade.Cod_Postal;

Page 29: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula WHERE (I)

SQL

Na cláusula WHERE pode constar qualquer expressão lógica. A expressão é avaliada linha a linha, isto é, para cada linha o SQL avalia o valor da expressão e, caso seja verdadeira, devolve a linha.

SELECT * FROM Cliente Where CodPostal > 1000 AND CodPostal < 2000;

SELECT * FROM Cliente Where (CodPostal > 1000 AND CodPostal < 2000) OR CodPostal = 3000;

Select * FROM CodPostal WHERE 1 = 1; (devolve todos os registos)

Page 30: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula WHERE (II)

SQL

Os principais operadores utilizados na cláusula WHERE são: =, <, >, >=, <=, <>, AND, OR, NOT, IN, LIKE, BETWEEN e ISNULL. O operador IN é verdadeiro quando um elemento faz parte de um conjunto. O operador permite a utilização de wildcards. O operador ISNULL permite lidar com valores NULL. Alguns exemplos:

SELECT * FROM CLIENTE WHERE CodPostal BETWEEN 1000,2000;

SELECT * FROM CLIENTE WHERE Nome LIKE ‘João%’ (todos os clientes começados por João)

SELECT * FROM Cliente WHERE Nacionalidade IN (‘Portugal’, ‘Brasil’); (todos os clientes portugueses ou brasileiros)

SELECT * FROM Cliente WHERE Nacionalidade NOT IN (‘Portugal’, ‘Brasil’); (todos os clientes excepto os portugueses e brasileiros)

SELECT * FROM Cliente WHERE Nacionalidade IS NOT NULL; (todos os clientes com nacionalidade conhecida)

Page 31: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusula WHERE (III)

SQL

A cláusula WHERE pode ser utilizada para produzir joins. Os dois seguintes comandos produzem o mesmo resultado (o 1º é mais eficiente devido às optimizações do SGBD).

SELECT * FROM Cliente INNER JOIN Localidade ON Cliente.Cod_Postal = Localidade.Cod_Postal;

SELECT * FROM Cliente, Localidade WHERE Cliente.Cod_Postal = Localidade.Cod_Postal;

Os seguinte comando produz um INNER JOIN apesar de estar indicado um LEFT JOIN (primeiro é efectuado o LEFT JOIN, mas posteriormente o SGBD apenas considera as linhas em que existe igualdade entre as chaves).

SELECT * FROM Cliente NATURAL LEFT OUTER JOIN Localidade WHERE Cliente.Cod_Postal = Localidade.Cod_Postal;

Page 32: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusulas GROUP BY e HAVING e Funções de Agregação (I)

SQL

Recorrendo apenas às cláusulas anteriores não é possível, por exemplo, efectuar certas operações estatísticas (somatórios, médias, etc.). Tal acontece porque as operações de agregação (que envolvem vários registos) não poderem ser calculadas linha a linha. Por exemplo, o comando para listar os códigos postais associados a mais do que dois clientes não pode ser efectuado tal como de seguida se apresenta:

SELECT CodPostal FROM Cliente WHERE COUNT(CodPostal) > 2

O comando é incorrecto porque a cláusula WHERE é testada linha a linha e, numa linha não é possível obter o total de códigos postais.

Page 33: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusulas GROUP BY e HAVING e Funções de Agregação (II)

SQL

As cláusulas GROUP BY e HAVING permitem manipular valores agregados. A cláusula GROUP BY permite a definição de grupos. A cláusula HAVING é equivalente à cláusula WHERE só que o seu argumento são expressões lógicas relativas aos agrupamentos criados pela cláusula GROUP BY. O exemplo anterior encontra-se bem formulado com o seguinte comando:

SELECT CodPostal FROM Cliente GROUP BY CodPostal HAVING COUNT(CodPostal) > 2;

A cláusula GROUP BY agrupa os clientes por código postal e a cláusula HAVING selecciona os grupos cujo número de elementos é superior a dois.

Page 34: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusulas GROUP BY e HAVING e Funções de Agregação (III)

SQL

O seguinte comando lista, para cada código postal, o número de clientes que a ele estão associados (desde que exista mais do que um cliente):

SELECT CodPostal, COUNT(CodPostal) FROM Cliente GROUP BY CodPostal HAVING COUNT(CodPostal) > 1;

Número Nome CodPostal

001 João 1500

013 Ana 2100

056 Luis 1500

001 Paula 2100

011 Nuno 1300

Cliente Número Nome CodPostal

001 João 1500

056 Luis 1500

CodPostal = 1500 (Total:2)

Número Nome CodPostal

013 Ana 2100

001 Paula 2100

CodPostal = 2100 (Total:2)

Número Nome CodPostal

011 Nuno 1300

CodPostal = 1300 (Total:1)

CodPostal COUNT(CodPostal)

1500 2

2100 2

1300 1

Nova tabela temporária

CodPostal COUNT(CodPostal)

1500 2

2100 2

Resultado Final

Page 35: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusulas GROUP BY e HAVING e Funções de Agregação (IV)

SQL

Sempre que existe uma função de agregação na cláusula SELECT, todos os restantes atributos da cláusula têm que estar incluídos na cláusula GROUP BY. O comando que de seguida se apresenta retorna o maior bilhete de identidade existente:

SELECT MAX(Bi) FROM Cliente;

Caso pretendêssemos visualizar o nome desse cliente, não poderíamos simplesmente acrescentar o atributo nome à cláusula SELECT. Pela regra anteriormente referida, teríamos que considerar a cláusula GROUP BY:

SELECT MAX(Bi), NOME FROM Cliente GROUP BY Nome;

No entanto, o resultado do comando seria a listagem de todos os nomes com a indicação do BI associado a cada nome. Mais adiante (Subquerys IV) apresenta-se a resolução desta interrogação.

Page 36: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Cláusulas GROUP BY e HAVING e Funções de Agregação (V)

SQL

Para além das funções COUNT e MAX, existem outras, tais como SUM, AVG e MIN.

Apenas a função COUNT não necessita de argumento: o primeiro comando retorna o total de registos de clientes enquanto o segundo devolve o total de clientes com o código postal conhecido:

SELECT COUNT(*) FROM Cliente;

SELECT COUNT(CodPostal) FROM Cliente;

Note-se que o segundo comando é equivalente ao seguinte:

SELECT COUNT(*) FROM Cliente WHERE CodPostal IS NOT NULL;

Page 37: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Subquerys (I)

SQL

Uma subquery é um comando SELECT dentro de um comando SELECT. Muitas interrogações apenas podem ser resolvidas através de subquerys. Um comando SELECT normalmente liga-se a outro através da cláusula WHERE.

Os operadores IN e EXISTS são normalmente utilizadas nas subquerys.

Operador IN devolve verdade quando um elemento pertence a um conjunto.

Operador EXISTS devolve verdade caso a subquery retorne pelo menos uma linha.

Page 38: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Subquerys (II)

SQL

Os dois comandos abaixo apresentados (equivalentes) devolvem os nomes que estão associados a pelo menos duas pessoas (dois BI’s) (sem a cláusula DISTINCT o comando retornaria os nomes duplicados; os sinónimos das tabelas são necessários para evitar ambiguidades na condição WHERE da subquery):

SELECT DISTINCT(Nome) FROM Cliente as Cliente1

WHERE NOME IN

(SELECT NOME FROM Cliente as Cliente2 WHERE

Cliente1.bi <> Cliente2.bi);

SELECT DISTINCT(Nome) FROM Cliente as Cliente1

WHERE EXISTS

(SELECT * FROM Cliente as Cliente2 WHERE

Cliente1.bi <> Cliente2.bi AND

Cliente1.Nome = Cliente2.Nome);

Page 39: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Subquerys (III)

SQL

Os operadores ALL (todos) e ANY (pelo menos um) também são frequentes nas subquerys. O comando para retornar o maior bilhete de identidade (e nome associado) existente é:

SELECT Nome, BI FROM Cliente

WHERE BI >= ALL

(SELECT BI FROM Cliente);

Caso pretendêssemos um bilhete de identidade que não fosse o menor, o comando seria:

SELECT Nome, BI FROM Cliente

WHERE BI > ANY

(SELECT BI FROM Cliente);

Page 40: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

SELECT – Subquerys (IV)

SQL

As subquerys também podem ser colocadas nas cláusula SELECT e FROM.

O seguinte exemplo devolve, para cada cliente, o total de facturas associadas:

SELECT Nome, (SELECT COUNT(*) FROM Factura

WHERE Factura.BI = Cliente.BI)

FROM Cliente;

O seguinte exemplo devolve, para cada cliente, o total de facturas associadas:

SELECT DISTINCT Nome

FROM (Select * From Cliente) as Cliente;

Page 41: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Comando UNION

SQL

A união de comandos SELECT é efectuada através do operador UNION.

O seguinte comando devolve os nomes dos clientes e fornecedores:

SELECT Nome FROM Cliente

UNION

SELECT Nome FROM Fornecedor;

Caso não pretendamos eliminar nomes duplicados o comando será:

SELECT Nome FROM Cliente

UNION ALL

SELECT Nome FROM Fornecedor;

Page 42: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Comando UPDATE

SQL

Um comando UPDATE para alteração de linhas obedece à seguinte estrutura:

UPDATE tabela a alterar

SET coluna a alterar = expressão

WHERE expressão lógica que indica quais as linhas que pretendemos alterar

O seguinte comando transforma os códigos postais 1200 em 1500:

UPDATE Cliente SET CodPostal = 1500

WHERE CodPostal = 1200;

Page 43: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Comando DELETE

SQL

Um comando DELETE para anulação de linhas obedece à seguinte estrutura:

DELETE FROM tabela a anular

WHERE expressão lógica que indica quais as linhas que pretendemos alterar

O seguinte comando apaga os códigos postais 1200

DELETE FROM Cliente

WHERE CodPostal = 1200;

Page 44: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Comando INSERT

SQL

Através do comando INSERT podem-se inserir uma linha ou várias linhas em simultâneo. Para inserir uma linha um comando INSERT obedece à seguinte estrutura:

INSERT INTO tabela a inserir (colunas onde vão ser inseridos os valores)

VALUES (valores a inserir)

Para inserir um conjunto de linhas, um comando INSERT obedece à seguinte estrutura:

INSERT INTO tabela a inserir (colunas onde vão ser inseridos os valores)

SELECT valores a inserir

FROM ...

INSERT INTO Produto (cod_produto, tipo) VALUES (123456, ‘MP’);INSERT INTO Produto (cod_produto, tipo) SELECT cod_materia, ‘MP’ FROM Materia_Prima;

Page 45: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Optimizações de Querys (I)

SQL

Na maioria dos SGBD’s a optimização de querys é feita automaticamente pelo planeador do SGBD. Ele, com base em estimativas de tempos e com base no histórico das transacções, decide qual a melhor estratégia a adoptar para executar uma query.

Exemplosselect PLAN('SELECT Titulo FROM Pub');

Scan pub sequentially

select PLAN('SELECT ISBN FROM Pub');Scan pub sequentially

select PLAN('SELECT ISBN FROM Pub Order By ISBN');Scan pub using index ndx_id

select PLAN('SELECT * FROM Pub Where Data = 1900 ‘); Scan pub using index ndx_data

select PLAN('SELECT * FROM Pub Where Data = 1900 or Data = 2000’);Scan pub sequentially

Índice apenas em ISBN e Data

Não vale a pena usar o índice

Page 46: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Optimizações de Querys (II)

SQL

select PLAN('SELECT Nome, Localidade FROM Cliente KEY JOIN Localidade');Scan Localidade sequentiallyScan Cliente using foreign key FK_Localidade

select PLAN('SELECT Nome, Localidade FROM Localidade KEY JOIN Cliente’);Scan Localidade sequentiallyScan Cliente using foreign key FK_Localidade

select PLAN('SELECT Nome FROM Cliente as CL1 Where NOT EXISTS (SELECT * From Cliente as CL2 Where CL2.Nome = CL1.Nome AND Cl2.Bi<>Cl1.BI)');

Scan Cliente AS CL1 sequentiallyScan Cliente AS CL2 sequentially

select PLAN('SELECT Nome FROM Cliente as CL1 Where Cl1.NOME NOT IN (SELECT CL2.Nome From Cliente as CL2 Where Cl2.Bi<>Cl1.BI)');

Scan Cliente AS CL1 sequentiallyScan Cliente AS CL2 sequentiallyDiferentes comandos produzem o mesmo plano

Page 47: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Views

SQL

As Views não são mais do que comandos SELECT armazenados. São por vezes denominadas tabelas temporárias. Note-se que o resultado de uma execução de uma view (os registos que ela devolve) depende dos registos armazenados no momento nas tabelas de suporte à view. As views podem ser utilizadas dentro de comandos SELECT.

CREATE VIEW Clientes_Lisboa (BI, Nome)AS Select BI, Nome FROM Cliente KEY JOIN Localidade Where Localidade = 'Lisboa'WITH CHECK OPTION;

Select Nome From Clientes_Lisboa;

As views não podem conter a cláusula ORDER BY e apenas permitem a inserção, remoção e alteração de registos caso não contenham as cláusulas GROUP BY e UNION. A cláusula CHECK OPTION rejeita alterações e inserções na view que não obedeçam ao critério da cláusula SELECT que a define.

Page 48: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Prepare Statement

SQL

O comando Prepare Statement permite optimizar acessos à base de dados que são efectuados múltiplas vezes em uma transacção. Quando um comando SQL é enviado ao SGBD, este, para além de ter o interpretar (parsing), tem de gerar um plano para a sua realização. O comando Prepare Statement evita que essas duas tarefas sejam executadas mais do que uma vez.

A comando apenas se justifica quando o SQL é utilizado dentro de outra linguagem de programação (Java, C, Visual Basic, etc.) ou em Stored Procedures (ver mais adiante).

Exemplo (simplificado, mais adiante apresenta-se um exemplo completo em JAVA)

PREPARE calc_factura("Update Factura Set Valor = ? Where Num_Factura = ? ;");calc_factura.setDouble(1, totalFactura);calc_factura.setInt(2, lastFactura);calc_factura.executeSQL()

Passagem de parâmetros

Execução

Page 49: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Stored Procedures

SQL

Os Stored Procedures (SP) são procedimentos SQL compilados e armazenados junto da base de dados. Trata-se da forma mais eficiente de executar comandos SQL. Para além dos comandos SQL é possível utilizar as habituais primitivas de controlo (If, While), os habituais operadores lógicos e variáveis. Trata-se no entanto de uma linguagem simples que não substitui as linguagens procedimentais (C, Java, etc.).

É possível passar parâmetros para um SP, assim como um SP retornar valores (nomeadamente o resultado de comandos SELECT). Os SP podem ser chamados dentro de um comando SELECT ou a partir de uma linguagem procedimental (através da primitiva CALL).

Page 50: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Stored Procedures - Exemplos

SQL

create procedure dba.newPubdelay()begin declare i integer; declare lastISBN integer; select max(ISBN) into lastISBN from Pub; set i=1; while i < 100000 loop set i=i+1 end loop; insert into pub(isbn) values(lastISBN+1); commit workend

Se após este SP for executado um outro idêntico sem o ciclo (simula uma pausa) ocorre uma situação de dead lock.

create procedure dba.getPubAno(in Par_Ano integer)result(ISBN integer,Titulo long varchar)begin select ISBN,Titulo from Pub where DAta = Par_Anoend

O comando CALL getPubAno(2000); retorna as publicações de 2000

Page 51: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Triggers (I)

SQL

Os triggers são procedimentos armazenados junto da base de dados que são associados a eventos que ocorrem nas tabelas. Através dos triggers o motor de base de dados reage automaticamente quando esses eventos (alterações dos dados nas tabelas) ocorrem. A forma como reagem é definida pelo procedimento associado ao trigger (um trigger apenas pode estar associado a um evento de uma tabela). Os eventos aos quais podem se associar os triggers: Insert, Update, Delete e Update Of (para cada um deles é necessário discriminar se o evento

ocorre antes ou depois da operação terminar).

Os eventos Insert, Update e Delete ocorrem ao nível do registo completo, enquanto que o evento Update Of ocorre ao nível de um campo da tabela (é necessário indicar qual o atributo no momento da definição do trigger).

Os triggers podem ainda ser row-level ou statement-level. Os triggers row-level ocorrem após cada linha da tabela ser alterada (anulada ou inserida). Os triggers statement-level ocorrem após uma operação sobre a tabela ser concluída (por exemplo, após um conjunto de registos ser inserido).

Page 52: SQL ÍndiceÁlgebra Pedro Ramos, DCTI/ISCTE Àlgebra e SQL Pedro Nogueira Ramos (Pedro.Ramos@iscte.pt) DCTI / ISCTE

Pedro Ramos, DCTI/ISCTE SQL ÍndiceÁlgebra

Triggers (II)

SQL

O procedimento associado ao trigger obedece no essencial à mesma sintaxe que os SP.

Exemplo: trigger (row-level) que é activado sempre que se insere uma matéria prima na tabela de produtos (insere um registo na tabela de matérias primas):

create trigger "dba".MateriaPrima after insert on Produtoreferencing new as new_produtofor each rowwhen(new_produto.Tipo='MP')begininsert into MateriaPrima(cod_produto) values(new_produto.cod_produto)end