Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Prévia do material em texto

Sistemas de Gerenciamento Sistemas de Gerenciamento 
de Banco de Dadosde Banco de Dados
Ramakrishnan • Gehrke
Tradução daTradução da
Terceira EdiçãoTerceira Edição
SISTEMAS DE GERENCIAMENTO 
DE BANCO DE DADOS
2011
Versão impressa
desta obra: 2008
Raghu Ramakrishnan
University of Wisconsin
Madison, Wisconsin, USA
Tradução da Terceira Edição
Johannes Gehrke
Cornell University
Ithaca, New York, USA
Tradução
Célia Taniwake
João Eduardo Nóbrega Tortello
Revisão Técnica
Elaine Parros Machado de Sousa
Professora Doutora do Departamento de Ciências de Computação — 
Instituto de Ciências Matemáticas e de Computação da Universidade de São Paulo
52 CAPÍTULO 3
O grau, também chamado aridade, de uma relação é o número de campos. A cardina-
lidade de uma instância de relação é o número de tuplas que ela contém. Na Figura 3.1, o 
grau da relação (o número de colunas) é cinco e a cardinalidade dessa instância é seis.
Um banco de dados relacional é uma coleção de relações com nomes distintos. O 
esquema de banco de dados relacional é a coleção de esquemas das relações presentes 
no banco de dados. Por exemplo, no Capítulo 1, discutimos o banco de dados de uma 
universidade com relações chamadas Alunos, Professores, Cursos, Salas, Matriculado, Mi-
nistra e Aula. Uma instância de um banco de dados relacional é uma coleção de instâncias 
de relação, uma por esquema de relação no esquema de banco de dados; naturalmente, 
cada instância de relação deve satisfazer as restrições de domínio nesse esquema.
3.1.1 Criando e Modifi cando Relações Usando SQL
A linguagem SQL padrão usa a palavra tabela para denotar relação e freqüentemente 
seguimos essa convenção ao discutirmos a SQL. O subconjunto da SQL que suporta a 
criação, exclusão e modificação de tabelas é chamado Data Definition Language (DDL 
— linguagem de definição de dados). Além disso, embora exista um comando que 
permite aos usuários definirem novos domínios, análogo aos comandos de definição de 
tipo em uma linguagem de programação, deixaremos a discussão sobre definição de 
domínio para a Seção 5.7. Por enquanto, consideraremos apenas os domínios que são 
tipos internos, como integerinteger.
A instrução CREATE TABLECREATE TABLE é usada para definir uma nova tabela.1 Para criarmos 
a relação Alunos, podemos usar a seguinte instrução:
CREATE TABLECREATE TABLE Alunos (id-aluno CHAR(20)CHAR(20),
nome CHAR(30)CHAR(30),
login CHAR(20)CHAR(20),
idade INTEGERINTEGER,
média REALREAL )
As tuplas são inseridas usando-se o comando INSERTINSERT. Podemos inserir uma única 
tupla na tabela Alunos, como segue:
INSERTINSERT
INTOINTO Alunos (id-aluno, nome, login, idade, média)
VALUESVALUES (53688, ‘Smith’, ‘smith@ee’, 18, 3,2)
Opcionalmente, podemos omitir a lista de nomes de coluna na cláusula INTOINTO e lis-
tar os valores na ordem apropriada, mas é considerado boa prática ser explícito quanto 
aos nomes de coluna.
Podemos excluir tuplas usando o comando DELETEDELETE. Podemos excluir todas as tu-
plas de Alunos com nome igual a Smith, usando o comando:
DELETEDELETE
FROMFROM Alunos A
WHEREWHERE A.nome = ‘Smith’
Podemos modificar os valores de coluna em uma linha existente usando o comando 
UPDATEUPDATE. Por exemplo, podemos incrementar a idade e decrementar a média do aluno 
com id-aluno 53688:
1 A SQL também fornece instruções para destruir tabelas e alterar as colunas associadas a uma tabela; 
discutiremos essas instruções na Seção 3.7.
esaito
Retângulo
O Modelo Relacional 53
 UPDATE UPDATE Alunos A
 SET SET A.idade = A.idade + 1, A.média = A.média – 1
 WHERE WHERE A.id-aluno = 53688
Esses exemplos ilustram alguns pontos importantes. A cláusula WHEREWHERE é aplicada 
primeiro e determina quais linhas devem ser modificadas. Então, a cláusula SETSET deter-
mina como essas linhas devem ser modificadas. Se a coluna que está sendo modificada 
também é usada para determinar o novo valor, o valor usado na expressão no lado 
direito do sinal de igualdade (=) é o valor antigo; ou seja, antes da modificação. Para 
ilustrar melhor esses pontos, considere a seguinte variação da consulta anterior:
 UPDATE UPDATE Alunos A
 SET SET A.média = A.média – 0,1
 WHERE WHERE A.média >= 3,3
Se essa consulta for aplicada na instância A1 de Alunos mostrada na Figura 3.1, 
obteremos a instância que aparece na Figura 3.3.
id-aluno nome login idade média
50000 Dave dave@cs 19 3,2
53666 Jones jones@cs 18 3,3
53688 Smith smith@ee 18 3,2
53650 Smith smith@math 19 3,7
53831 Madayan madayan@music 11 1,8
53832 Guldu guldu@music 12 2,0
Figura 3.3 Instância A1 de Alunos após a atualização.
3.2 RESTRIÇÕES DE INTEGRIDADE SOBRE RELAÇÕES
Um banco de dados é tão bom quanto as informações nele armazenadas e, portanto, 
um SGBD deve ajudar a evitar a entrada de informações incorretas. Uma restrição de 
integridade (RI) é uma condição especificada sobre um esquema de banco de dados e 
limita os dados que podem ser armazenados em uma instância do banco de dados. Se 
uma instância do banco de dados satisfaz todas as restrições de integridade especifi-
cadas em seu esquema, então ela é uma instância válida. Um SGBD impõe restrições 
de integridade, no sentido de que ele permite o armazenamento apenas de instâncias 
válidas no banco de dados.
As restrições de integridade são especificadas e verificadas em diferentes ocasiões:
1. Quando o administrador ou o usuário final define um esquema de banco de dados, 
ele especifica as RIs que devem valer em qualquer instância desse banco de dados.
2. Quando um aplicativo de banco de dados é executado, o SGBD verifica se existem 
violações e proíbe alterações nos dados que violem as RIs especificadas. (Em al-
gumas situações, em vez de proibir a alteração, o SGBD poderia fazer algumas 
alterações de compensação nos dados, para garantir que a instância do banco de 
dados satisfaça todas as RIs. Em qualquer caso, não são permitidas alterações no 
banco de dados para criar uma instância que viole qualquer RI.) É importante es-
pecificar exatamente quando as restrições de integridade são verificadas, em relação 
lfilho
Retângulo
54 CAPÍTULO 3
à instrução que causa a alteração nos dados e à transação da qual ela faz parte. 
Discutiremos esse aspecto no Capítulo 16, após apresentarmos com mais detalhes o 
conceito de transação, introduzido no Capítulo 1.
Muitos tipos de restrições de integridade podem ser especificados no modelo rela-
cional. Já vimos um exemplo de restrição de integridade nas restrições de domínio 
associadas a um esquema de relação (Seção 3.1). Em geral, outros tipos de restrições 
também podem ser especificados; por exemplo, dois alunos não podem ter o mesmo 
valor de id-aluno. Nesta seção, discutiremos as restrições de integridade, além das 
restrições de domínio, que um administrador ou usuário de banco de dados pode espe-
cificar no modelo relacional.
3.2.1 Restrições de Chave
Considere a relação Alunos e a restrição de que dois alunos não podem ter a mesma 
identificação. Essa RI é um exemplo de restrição de chave. Uma restrição de chave é 
uma declaração de que certo subconjunto mínimo dos campos de uma relação é um 
identificador único para uma tupla. Um conjunto de campos que identifica uma tupla 
de acordo com uma restrição de chave é chamado chave candidata da relação; freqüen-
temente, abreviamos isso apenas como chave. No caso da relação Alunos, o (conjunto 
de campos contendo apenas o) campo id-aluno é uma chave candidata.
Vamos analisar melhor a definição anterior de chave (candidata). Existem duas 
partes na definição:2
1. Duas tuplas distintas em uma instância válida (uma instância que satisfaz todas as 
RIs, incluindo a restrição de chave) não podem ter valores idênticos em todos os 
campos de uma chave.
2. Nenhum subconjunto do conjunto de campos em uma chave é um identificador 
único para uma tupla.
A primeira parte da definição significa que, em qualquer instância válida, os valores 
nos campos de chave identificam univocamente uma tupla na instância. Ao especificar 
uma restrição dechave, o administrador ou usuário do banco de dados deve certi-
ficar-se de que essa restrição não o impeça de armazenar um conjunto “correto” de 
tuplas. (Um comentário semelhante também se aplica à especificação de outros tipos 
de RIs.) A noção de “correto” aqui depende da natureza dos dados que estão sendo 
armazenados. Por exemplo, vários alunos podem ter o mesmo nome, embora cada um 
tenha uma identificação única. Se o campo nome for declarado como uma chave, o 
SGBD não permitirá que a relação Alunos contenha duas tuplas descrevendo alunos 
diferentes com o mesmo nome!
A segunda parte da definição significa, por exemplo, que o conjunto de campos 
{id-aluno, nome} não é uma chave para Alunos, pois esse conjunto contém a cha-
ve {id-aluno}. O conjunto {id-aluno, nome} é um exemplo de superchave, que é um 
conjunto de campos que contém uma chave.
Veja novamente a instância da relação Alunos na Figura 3.1. Observe que duas 
linhas diferentes sempre têm valores de id-aluno diferentes; id-aluno é uma chave e 
identifica uma tupla univocamente. Entretanto, isso não vale para campos que não são 
chave. Por exemplo, a relação contém duas linhas com Smith no campo nome.
2 O termo chave é muito utilizado. No contexto dos métodos de acesso, falamos sobre chaves de pesquisa, 
que são muito diferentes.
O Modelo Relacional 55
Note que é garantido que toda relação tenha uma chave. Como uma relação é 
um conjunto de tuplas, o conjunto de todos os campos é sempre uma superchave. Se 
outras restrições valem, algum subconjunto dos campos pode formar uma chave, do 
contrário o conjunto de todos os campos é uma chave.
Uma relação pode ter várias chaves candidatas. Por exemplo, os campos login e 
idade da relação Alunos, em conjunto, também podem identificar alunos de maneira 
única. Ou seja, {login, idade} também é uma chave. Pode parecer que login é uma 
chave, pois não existem duas linhas no exemplo de instância que tenham o mesmo 
valor de login. Entretanto, a chave deve identificar as tuplas univocamente em todas 
as instâncias válidas possíveis da relação. Dizendo que {login, idade} é uma chave, o 
usuário está declarando que dois alunos podem ter o mesmo login ou a mesma idade, 
mas não ambos.
Além de todas as chaves candidatas disponíveis, um projetista de banco de dados 
pode identificar uma chave primária. Intuitivamente, uma tupla pode ser referenciada 
em qualquer outra parte do banco de dados armazenando-se os valores de seus campos 
de chave primária. Por exemplo, podemos nos referir a uma tupla de Alunos armaze-
nando seu valor de id-aluno. Como conseqüência dessa maneira de referência às tuplas 
de alunos, freqüentemente as tuplas são acessadas especificando-se seu valor de id-alu-
no. Em princípio, podemos usar qualquer chave, e não apenas a chave primária, para 
nos referirmos a uma tupla. Entretanto, usar a chave primária é preferível, pois é ela 
que o SGBD espera — esse é o significado de projetar uma chave candidata em par-
ticular como chave primária — e para a qual faz otimizações. Por exemplo, o SGBD 
pode criar um índice com os campos de chave primária como chave de pesquisa, para 
tornar eficiente a recuperação de uma tupla, dado seu valor de chave primária. A idéia 
da referência a uma tupla será mais bem desenvolvida na próxima seção.
Especifi cando Restrições de Chave em SQL
Na SQL, podemos declarar que um subconjunto das colunas de uma tabela constituem 
uma chave, usando a restrição UNIQUEUNIQUE. No máximo uma dessas chaves candidatas 
pode ser declarada como chave primária, usando-se a restrição PRIMARY KEYPRIMARY KEY. (A 
SQL não exige que essas restrições sejam declaradas para uma tabela.)
Vamos rever nosso exemplo de definição de tabela e especificar informações de chave:
 CREATE TABLE CREATE TABLE Alunos ( id-aluno CHAR(20)CHAR(20),
 nome CHAR(30)CHAR(30),
 login CHAR(20)CHAR(20),
 idade INTEGERINTEGER,
 média REALREAL,
 UNIQUE UNIQUE (nome, idade),
 CONSTRAINT CONSTRAINT Chave Alunos PRIMARY KEYPRIMARY KEY (id-aluno) )
Essa definição diz que id-aluno é a chave primária e a combinação de nome e idade 
também é uma chave. A definição da chave primária também ilustra como podemos 
nomear uma restrição, precedendo-a com CONSTRAINTCONSTRAINT nome-da-restrição. Se a restri-
ção for violada, seu nome será retornado e poderá ser usado para identificar o erro.
3.2.2 Restrições de Chave Estrangeira
Às vezes, as informações armazenadas em uma relação estão ligadas às informações 
armazenadas em outra relação. Se uma das relações for modificada, a outra deverá ser 
verificada e, talvez, modificada, para manter os dados consistentes. Uma RI envolvendo 
56 CAPÍTULO 3
as duas relações deverá ser especificada, caso um SGBD precise fazer tais verificações. A 
RI mais comum envolvendo duas relações é uma restrição de chave estrangeira.
Suponha que, além de Alunos, tenhamos uma segunda relação:
 Matriculado(id-aluno: stringstring, id-curso: stringstring, nota: stringstring)
Para garantir que apenas estudantes legítimos possam se matricular nos cursos, 
qualquer valor que apareça no campo id-aluno de uma instância da relação Matricu-
lado também deve aparecer no campo id-aluno de alguma tupla na relação Alunos. 
O campo id-aluno de Matriculado é chamado chave estrangeira e se refere a Alunos. 
A chave estrangeira na relação de referência (Matriculado, em nosso exemplo) deve 
corresponder à chave primária da relação referenciada (Alunos); ou seja, ela deve ter o 
mesmo número de colunas e tipos de dados compatíveis, embora os nomes das colunas 
possam ser diferentes.
Essa restrição está ilustrada na Figura 3.4. Conforme mostra a figura, podem existir 
tuplas de Alunos que não sejam referenciadas a partir de Matriculado (por exemplo, o alu-
no com id-aluno=50000). Entretanto, todo valor de id-aluno que aparece na instância da 
tabela Matriculado aparece na coluna de chave primária de uma linha na tabela Alunos.
Chave estrangeira Chave primária
id-curso nota id-aluno id-aluno nome login idade média
Carnatic101 C 53831 50000 Dave dave@cs 19 3,3
Reggae203 B 53832 53666 Jones jones@cs 18 3,4
Topology112 A 53650 53688 Smith smith@ee 18 3,2
History105 B 53666 53650 Smith smith@math 19 3,8
53831 Madayan madayan@music 11 1,8
53832 Guldu guldu@music 12 2,0
Matriculado
(relação que referencia)
Alunos
(relação referenciada)
Figura 3.4 Integridade referencial.
Se tentarmos inserir a tupla ·55555, Art104, AÒ em M1, a RI será violada, pois 
não há nenhuma tupla em A1 com id-aluno 55555; o sistema de banco de dados deve 
rejeitar essa inserção. Analogamente, se excluirmos a tupla ·53666, Jones, jones@
cs, 18, 3,4Ò de A1, violaremos a restrição de chave estrangeira, pois a tupla ·53666, 
History105, B Ò em M1 contém o valor de id-aluno 53666, o id-aluno da tupla de Alu-
nos excluída. O SGBD deve proibir a exclusão ou, talvez, excluir também a tupla de 
Matriculado que referencia a tupla de Alunos excluída. Discutiremos as restrições de 
chave estrangeira e seu impacto sobre as atualizações na Seção 3.3.
Finalmente, notamos que uma chave estrangeira poderia referenciar a mesma re-
lação. Por exemplo, poderíamos ampliar a relação Alunos com uma coluna chamada 
parceiro e declarar essa coluna como uma chave estrangeira referindo-se a Alunos. 
Intuitivamente, cada aluno poderia então ter um parceiro e o campo parceiro conteria 
o id-aluno do parceiro. O leitor observador sem dúvida perguntará: “E se um aluno 
não tiver (ainda) um parceiro?”. Essa situação é tratada na SQL usando-se um valor 
especial chamado null. O uso de null em um campo de uma tupla significa que o 
O Modelo Relacional 57
valor nesse campo é desconhecido ou não é aplicável (por exemplo, não conhecemos o 
parceiro ainda ou não há nenhum parceiro). A presença de null em um campo de cha-
ve estrangeira não viola a restrição de chave estrangeira. Entretanto, valores null não 
podem aparecer em um campo de chave primária (pois os campos de chave primária 
são usados para identificar uma tupla univocamente). Discutiremosmelhor os valores 
null no Capítulo 5.
Especifi cando Restrições de Chave Estrangeira em SQL
Vamos definir Matriculado(id-aluno: stringstring, id-curso: stringstring, nota: stringstring):
 CREATE TABLE CREATE TABLE Matriculado ( id-aluno CHAR(20)CHAR(20),
 id-curso CHAR(20)CHAR(20),
 nota CHAR(10)CHAR(10),
 PRIMARY KEY PRIMARY KEY (id-aluno, id-curso),
 FOREIGN KEY FOREIGN KEY (id-aluno) REFERENCESREFERENCES Alunos )
A restrição de chave estrangeira diz que todo valor de id-aluno em Matriculado 
também deve aparecer em Alunos; ou seja, id-aluno em Matriculado é uma chave es-
trangeira referenciando Alunos. Especificamente, todo valor de id-aluno em Matricu-
lado deve aparecer como o valor do campo de chave primária, id-aluno, de Alunos. A 
propósito, a restrição de chave primária de Matriculado diz que um aluno tem exata-
mente uma nota para cada curso em que está matriculado. Se quisermos registrar mais 
de uma nota por aluno, por curso, devemos alterar a restrição de chave primária.
3.2.3 Restrições Gerais
As restrições de domínio, de chave primária e de chave estrangeira são consideradas 
parte fundamental do modelo de dados relacional e recebem atenção especial na maio-
ria dos sistemas comerciais. Às vezes, entretanto, é necessário especificar restrições 
mais gerais.
Por exemplo, podemos exigir que a idade dos alunos esteja dentro de certo intervalo 
de valores; dada essa especificação de RI, o SGBD rejeitará as inserções e atualizações 
que violarem a restrição. Isso é muito útil na prevenção de erros de entrada de dados. 
Se especificarmos que todos os alunos devem ter pelo menos 16 anos, a instância de 
Alunos mostrada na Figura 3.1 será inválida, pois dois alunos têm idade menor do que 
essa. Se proibirmos a inserção dessas duas tuplas, teremos uma instância válida, como 
se vê na Figura 3.5.
id-aluno nome login idade média
53666 Jones jones@cs 18 3,4
53688 Smith smith@ee 18 3,2
53650 Smith smith@math 19 3,8
Figura 3.5 Uma instância A2 da relação Alunos.
A RI que diz que os alunos devem ser maiores de 16 anos pode ser considerada 
uma restrição de domínio estendida, pois estamos basicamente definindo o conjunto de 
valores de idade permitidos de maneira mais restrita do que é possível usando simples-
mente um domínio padrão, como integerinteger. Em geral, contudo, podem ser especifica-
58 CAPÍTULO 3
das restrições que vão bem além das de domínio, de chave e de chave estrangeira. Por 
exemplo, poderíamos exigir que todo aluno cuja idade fosse maior do que 18 devesse 
ter uma média maior do que 3.
Os sistemas de banco de dados relacionais atuais suportam essas restrições gerais 
na forma de restrições de tabela e assertivas. As restrições de tabela são associadas a 
uma única tabela e verificadas quando essa tabela é modificada. Em contraste, as as-
sertivas envolvem várias tabelas e são verificadas quando qualquer uma dessas tabelas 
é modificada. Tanto as restrições de tabela como as assertivas podem usar o poder to-
tal das consultas SQL para especificar a restrição desejada. Discutiremos o suporte da 
SQL para restrições de tabela e assertivas na Seção 5.7, pois uma avaliação completa 
de seu poder exige um bom entendimento dos recursos de consulta da SQL.
3.3 VERIFICANDO RESTRIÇÕES DE INTEGRIDADE
Conforme observamos anteriormente, as RIs são especificadas quando uma relação é 
criada e verificadas quando uma relação é modificada. O impacto das restrições de 
domínio, PRIMARY KEYPRIMARY KEY e UNIQUEUNIQUE é simples de entender: se um comando de inserção, 
exclusão ou atualização causa uma violação, ele é rejeitado. Toda violação de RI em 
potencial geralmente é verificada no final da execução de cada instrução SQL, embora 
possa ser adiada até o final da transação que está executando a instrução, conforme 
veremos na Seção 3.3.1.
Considere a instância A1 de Alunos mostrada na Figura 3.1. A inserção a seguir 
viola a restrição de chave primária, porque já existe uma tupla com id-aluno 53688, e 
será rejeitada pelo SGBD:
 INSERTINSERT
 INTO INTO Alunos (id-aluno, nome, login, idade, media)
 VALUES VALUES (53688, ‘Mike’, ‘mike@ee’, 17, 3,4)
A inserção a seguir viola a restrição de que a chave primária não pode conter null:
 INSERTINSERT
 INTO INTO Alunos (id-aluno, nome, login, idade, media)
 VALUES VALUES (null, ‘Mike’, ‘mike@ee’, 17, 3,4)
É claro que surge um problema semelhante quando tentamos inserir uma tupla 
com um valor em um campo que não esteja no domínio associado a esse campo; isto 
é, quando violamos uma restrição de domínio. A exclusão de tuplas não causa uma 
violação de restrições de domínio, chave primária ou exclusiva. Entretanto, uma atua-
lização pode causar violações semelhantes a uma inserção:
 UPDATE UPDATE Alunos A
 SET SET A.id-aluno = 50000
 WHERE WHERE A.id-aluno = 53688
Essa atualização viola a restrição de chave primária, pois já existe uma tupla com 
id-aluno 50000.
O impacto das restrições de chave estrangeira é mais complexo, pois às vezes a SQL 
tenta retificar uma violação de restrição de chave estrangeira, em vez de simplesmente 
rejeitar a alteração. Discutiremos as etapas de verificação da integridade referencial 
executadas pelo SGBD em termos de nossas tabelas Matriculado e Alunos, com a 
restrição de chave estrangeira de que Matriculado.id-aluno é uma referência para (a 
chave primária de) Alunos.
O Modelo Relacional 59
Além da instância A1 de Alunos, considere a instância de Matriculado mostrada na 
Figura 3.4. As exclusões de tuplas de Matriculado não violam a integridade referen-
cial, mas as inserções de tuplas de Matriculado poderiam violar. A inserção a seguir é 
inválida, pois não há nenhuma tupla de Alunos com id-aluno 51111:
 INSERTINSERT
 INTO INTO Matriculado (id-curso, nota, id-aluno)
 VALUES VALUES (‘Hindi101’, ‘B’, 51111)
Por outro lado, inserções de tuplas em Alunos não violam a integridade referencial, 
e as exclusões poderiam causar violações. Além disso, atualizações em Matriculado 
ou em Alunos que alteram o valor de id-aluno (respectivamente, id-aluno) poderiam 
violar a integridade referencial.
A SQL fornece várias maneiras alternativas de tratar de violações de chave estran-
geira. Devemos considerar três perguntas básicas:
1. O que devemos fazer se uma linha de Matriculado é inserida, com um valor na 
coluna id-aluno que não aparece em nenhuma linha da tabela Alunos?
 Nesse caso, o comando INSERTINSERT é simplesmente rejeitado.
2. O que devemos fazer se uma linha de Alunos é excluída?
 As opções são:
Excluir todas as linhas de Matriculado que referenciam a linha de Alunos 
excluída.
Proibir a exclusão da linha de Alunos, caso uma linha de Matriculado a refe-
rencie.
Configurar a coluna id-aluno com o valor de id-aluno de algum aluno (existen-
te) “padrão”, para cada linha de Matriculado que referencie a linha de Alunos 
excluída.
Para cada linha de Matriculado que referencia a linha excluída, configurar a 
coluna id-aluno como null. Em nosso exemplo, esta opção entra em conflito 
com o fato de que id-aluno faz parte da chave primária de Matriculado e, por-
tanto, não pode ser configurada como null. Assim, em nosso exemplo estamos 
limitados às três primeiras opções, embora esta quarta opção (configurar a 
chave estrangeira como null) esteja disponível em geral.
3. O que devemos fazer se o valor da chave primária de uma linha de Alunos for 
atualizada?
As opções aqui são semelhantes às do caso anterior.
A SQL nos permite escolher qualquer uma das quatro opções em DELETEDELETE e UPDA-UPDA-
TETE. Por exemplo, podemos especificar que, quando uma linha de Alunos é excluída, to-
das as linhas de Matriculado que se referem a ela também devem ser excluídas, mas que, 
quando a coluna id-aluno de uma linha de Alunos é modificada, essa atualização deve ser 
rejeitada, caso uma linha de Matriculado se refira à linha de Alunos modificada:
 CREATE TABLE CREATE TABLE Matriculado ( id-aluno CHAR(20)CHAR(20),
 id-curso CHAR(20)CHAR(20),
 nota CHAR(10)CHAR(10),
 PRIMARY KEY PRIMARY KEY(id-aluno, id-curso),
 FOREIGN KEY FOREIGN KEY (id-aluno) REFERENCESREFERENCES Alunos
 ON DELETE CASCADEON DELETE CASCADE
 ON UPDATE NO ACTION ON UPDATE NO ACTION )
■
■
■
■
60 CAPÍTULO 3
As opções são especificadas como parte da declaração da chave estrangeira. A op-
ção padrão é NO ACTIONNO ACTION, que significa que a ação (DELETEDELETE ou UPDATEUPDATE) deve ser 
rejeitada. Assim, em nosso exemplo, a cláusula ON UPDATEON UPDATE poderia ser omitida, com 
o mesmo efeito. A palavra-chave CASCADECASCADE diz que, se uma linha de Alunos for excluída, 
todas as linhas de Matriculado que se referem a ela também serão excluídas. Se a cláu-
sula UPDATEUPDATE especificasse CASCADECASCADE e a coluna id-aluno de uma linha de Alunos fosse 
atualizada, essa atualização também seria executada em cada linha de Matriculado 
que se referisse à linha de Alunos atualizada.
Se uma linha de Alunos for excluída, podemos trocar a matrícula para um alu-
no ‘padrão’, usando ON DELETE SET DEFAULTON DELETE SET DEFAULT. O aluno padrão é especificado 
como parte da definição do campo id-aluno em Matriculado; por exemplo, id-aluno 
CHAR(20)CHAR(20) DEFAULTDEFAULT ‘53666’. Embora a especificação de um valor padrão seja apro-
priada em algumas situações (por exemplo, um fabricante de peças padrão, caso um 
fabricante em particular saia do ramo), não é adequado trocar as matrículas para um 
aluno padrão. A solução correta nesse exemplo é excluir também todas as tuplas de 
matrícula do aluno excluído (isto é, CASCADECASCADE) ou rejeitar a atualização.
A SQL também permite o uso de null como valor padrão, especificando-se ON DE-ON DE-
LETE SET NULLLETE SET NULL.
3.3.1 Transações e Restrições
Conforme vimos no Capítulo 1, um programa executado em um banco de dados é cha-
mado transação e pode conter várias instruções (consultas, inserções, atualizações etc.) 
que acessam o banco de dados. Se (a execução de) uma instrução em uma transação 
violar uma restrição de integridade, o SGBD deveria detectar isso imediatamente, ou 
todas as restrições deveriam ser verificadas em conjunto, imediatamente antes que a 
transação termine?
Por padrão, uma restrição é verificada no final de cada instrução SQL que possa 
levar a uma violação e, se houver violação, a instrução será rejeitada. Às vezes essa 
estratégia é inflexível. Considere as variantes das relações Alunos e Cursos a seguir; 
todo aluno é obrigado a ter um curso de distinção, e todo curso é obrigado a ter um 
monitor, que é algum aluno.
CREATE TABLE CREATE TABLE AlunosAlunos ( id-aluno CHAR(20)CHAR(20),
 nome CHAR(30)CHAR(30),
 login CHAR(20)CHAR(20),
 idade INTEGERINTEGER,
 distinção CHAR(10) NOT NULLCHAR(10) NOT NULL,
 media REALREAL )
 PRIMARY KEY PRIMARY KEY (id-aluno),
 FOREIGN KEY FOREIGN KEY (distinção) REFERENCESREFERENCES Cursos (id-curso)
CREATE TABLECREATE TABLE Cursos ( id-curso CHAR(10)CHAR(10),
 nomec CHAR(10)CHAR(10),
 créditos INTEGERINTEGER,
 monitor CHAR(20) NOT NULLCHAR(20) NOT NULL,
 PRIMARY KEY PRIMARY KEY (id-curso)
 FOREIGN KEY FOREIGN KEY (monitor) REFERENCESREFERENCES Alunos (id-aluno))
Quando uma tupla de Alunos é inserida, é feita uma verificação para saber se o 
curso de distinção está na relação Cursos e, quando uma tupla de Cursos é inserida, 
O Modelo Relacional 61
é feita uma verificação para saber se o monitor está na relação Alunos. Como vamos 
inserir a primeira tupla de curso ou de aluno? Uma não pode ser inserida sem a outra. 
A única maneira de realizar essa inserção é adiando a verificação da restrição, que 
normalmente seria feita no final de uma instrução INSERTINSERT.
A SQL permite que uma restrição esteja no modo DEFERREDDEFERRED ou IMMEDIATEIMMEDIATE.
SET CONSTRAINTSET CONSTRAINT nome-restrição DEFERREDDEFERRED
Uma restrição no modo adiado (deferred) é verificada no momento da efetivação 
da transação (commit). Em nosso exemplo, as restrições de chave estrangeira sobre 
Alunos e Cursos podem ambas ser declaradas no modo adiado. Podemos então inserir 
um aluno com um curso de distinção inexistente (tornando o banco de dados tempora-
riamente inconsistente), inserir o curso (restaurando a consistência) e depois efetivar 
e verificar se as duas restrições são satisfeitas.
3.4 CONSULTANDO DADOS RELACIONAIS
Uma consulta de banco de dados relacional (abreviadamente, consulta) é uma pergun-
ta sobre os dados, e a resposta consiste em uma nova relação contendo o resultado. Por 
exemplo, poderíamos querer encontrar todos os alunos com menos de 18 anos ou todos 
os alunos matriculados em Reggae203. Uma linguagem de consulta é uma linguagem 
especializada para escrever consultas.
A SQL é a linguagem de consulta comercial mais popular para um SGBD relacio-
nal. Apresentaremos agora alguns exemplos de SQL que ilustram como as relações 
podem ser facilmente consultadas. Considere a instância da relação Alunos mostrada 
na Figura 3.1. Podemos recuperar as linhas correspondentes aos alunos que têm menos 
de 18 anos com a seguinte consulta SQL:
esaito
Retângulo
SQL: Consultas, Restrições, Gatilhos 113
O material on-line inclui instruções de como configurar o Oracle, o IBM DB2, o Micro-
soft SQL Server, e o MySQL, e os scripts para criação de tabelas e consultas de exemplo.
5.2 O FORMATO DE UMA CONSULTA SQL BÁSICA
Esta seção apresenta a sintaxe de uma consulta SQL simples e explica seu significa-
do através de uma estratégia de avaliação conceitual, que é uma forma de avaliar a 
consulta, intencionalmente mais fácil de entender, mas não tão eficiente. Um SGBD 
executaria normalmente uma consulta de uma forma diferente e mais eficiente.
O formato básico de uma consulta SQL é:
 SELECTSELECT [ DISTINCT ][ DISTINCT ] lista-seleção
 FROMFROM lista-from
 WHEREWHERE qualificação
id-marin nome-marin avaliação idade
22 Dustin 7 45,0
29 Brutus 1 33,0
31 Lubber 8 55,5
32 Andy 8 25,5
58 Rusty 10 35,0
64 Horatio 7 35,0
71 Zorba 10 16,0
74 Horatio 9 35,0
85 Art 3 25,5
95 Bob 3 63,5 
id-marin id-barco dia
22 101 10/10/98
22 102 10/10/98
22 103 10/8/98
22 104 10/7/98
31 102 11/10/98
31 103 11/6/98
31 104 11/12/98
64 101 9/5/98
64 102 9/5/98
74 103 9/8/98
Figura 5.1 Uma instância M3 de Marinheiros. Figura 5.2 Uma instância R2 de Reservas.
id-barco nome-barco cor
101 Interlake azul
102 Interlake vermelho
103 Clipper verde
104 Marine vermelho
Figura 5.3 Uma instância B1 de Barcos.
Toda consulta deve ter uma cláusula SELECTSELECT, que especifica as colunas a serem 
mantidas no resultado, e uma cláusula FROMFROM, que especifica um produto cartesiano 
de tabelas. A cláusula opcional WHEREWHERE especifica as condições de seleção nas tabelas 
mencionadas na cláusula FROMFROM.
Uma consulta como essa corresponde intuitivamente a uma expressão de álgebra 
relacional envolvendo seleções, projeções e produtos cartesianos. A íntima relação en-
tre a SQL e a álgebra relacional é a base para a otimização de consulta em um SGBD 
relacional, conforme veremos nos Capítulos 12 e 15. De fato, os planos de execução 
lfilho
Retângulo
114 CAPÍTULO 5
das consultas SQL são representados usando uma variação das expressões de álgebra 
relacional (Seção 15.1).
Vamos considerar um exemplo simples.
(C15) Encontre os nomes e as idades de todos os marinheiros.
 SELECTSELECT DISTINCTDISTINCT M.nome-marin, M.idade
 FROMFROM Marinheiros M
A resposta é um conjunto de linhas, sendo cada linha um par ·nome-marin, idadeÒ. Se 
dois ou mais marinheiros tiverem o mesmo nome e a mesma idade, a resposta conterá 
apenas um par com esse nome e idade. Essa consulta é equivalente a aplicar o opera-
dor projeção da álgebra relacional.
Se omitíssemos a palavra reservada DISTINCTDISTINCT, obteríamos uma cópia da linha 
·m, iÒ para cada marinheiro com nome m e idade i; a resposta seria um multiconjunto 
de linhas. Um multiconjunto é semelhante a um conjunto por ser uma coleção desor-
denada de elementos, mas pode conter diversas cópias de cada elemento, e o número 
de cópias é significativo — dois multiconjuntos poderiam ter os mesmoselementos e 
ainda assim ser diferentes em razão do número de cópias ser diferente para alguns ele-
mentos. Por exemplo, {a, b, b} e {b, a, b} denotam o mesmo multiconjunto, e diferem 
do multiconjunto {a, a, b}.
A resposta a essa consulta com e sem a palavra reservada DISTINCTDISTINCT na instância 
M3 de Marinheiros é ilustrada nas Figuras 5.4 e 5.5. A única diferença é que a tupla 
de Horatio aparecerá duas vezes se DISTINCTDISTINCT for omitido; isso ocorre porque há dois 
marinheiros chamados Horatio, de idade 35.
nome-marin idade
Dustin 45,0
Brutus 33,0
Lubber 55,5
Andy 25,5
Rusty 35,0
Horatio 35,0
Zorba 16,0
Art 25,5
Bob 63,5 
nome-marin idade
Dustin 45,0
Brutus 33,0
Lubber 55,5
Andy 25,5
Rusty 35,0
Horatio 35,0
Zorba 16,0
Horatio 35,0
Art 25,5
Bob 63,5
 Figura 5.4 Resposta a C15. Figura 5.5 Resposta a C15 sem DISTINCTDISTINCT.
Nossa próxima consulta é equivalente a uma aplicação do operador seleção da ál-
gebra relacional.
(C11) Encontre todos os marinheiros com uma avaliação acima de 7.
 SELECTSELECT M.id-marin, M.nome-marin, M.avaliação, M.idade
 FROMFROM Marinheiros ASAS M
 WHEREWHERE M.avaliação > 7
SQL: Consultas, Restrições, Gatilhos 115
Essa consulta utiliza a palavra reservada opcional ASAS para introduzir uma variável 
de intervalo. Aliás, quando desejamos recuperar todas as colunas, como nessa consul-
ta, a SQL provê um atalho conveniente: Podemos escrever simplesmente SELECT *SELECT *. 
Esta notação é útil para consultas interativas, mas é um estilo pobre para as consultas 
que deverão ser reutilizadas e mantidas porque o esquema do resultado não é claro a 
partir da consulta propriamente dita; devemos referenciar ao esquema da tabela sub-
jacente Marinheiros.
Conforme esses dois exemplos ilustram, a cláusula SELECTSELECT é usada realmente para 
fazer projeção, enquanto as seleções, no sentido da álgebra relacional, são expressas 
usando a cláusula WHEREWHERE! Essa confusão entre a nomeação dos operadores de seleção e 
projeção na álgebra relacional e na sintaxe da SQL é um acidente histórico infeliz.
Consideraremos agora a sintaxe de uma consulta SQL básica com mais detalhes.
A lista-from da cláusula FROMFROM é uma lista de nomes de tabela. Um nome de tabela 
pode ser seguido por uma variável de intervalo (range viariable), que é particu-
larmente útil quando o mesmo nome de tabela aparece mais do que uma vez na 
lista-from.
A lista-seleção é uma lista de (expressões envolvendo) nomes de coluna das tabelas 
nomeadas na lista-from. Os nomes de coluna podem ser prefixados por uma variá-
vel de intervalo.
A qualificação da cláusula FROMFROM é uma combinação booleana (isto é, uma expressão 
usando os conectivos lógicos ANDAND, OROR e NOTNOT) de condições no formato expressão opop 
expressão, onde opop é um dos operadores de comparação {<, <=, = < >, >=, >}.2 
Uma expressão é um nome de coluna, uma constante ou uma expressão (aritmética 
ou de string).
A palavra reservada DISTINCTDISTINCT é opcional. Ela indica que a tabela computada 
como uma resposta a essa consulta não deve conter duplicatas, ou seja, duas cópias 
da mesma linha. O padrão é que as duplicatas não sejam eliminadas.
Embora as regras precedentes descrevam (informalmente) a sintaxe de uma con-
sulta SQL básica, elas não nos informam o significado de uma consulta. A resposta a 
uma consulta é por si só uma relação — que em SQL! é um multiconjunto de linhas 
— cujo conteúdo pode ser compreendido considerando-se a seguinte estratégia de ava-
liação conceitual:
1. Compute o produto cartesiano das tabelas da lista-from.
2. Exclua as linhas no produto cartesiano que não satisfazem as condições de qualifi-
cação.
3. Exclua as colunas que não aparecem na lista-seleção.
4. Se DISTINCTDISTINCT for especificado, elimine as linhas duplicatas.
Essa estratégia direta de avaliação conceitual torna explícitas as linhas que devem 
ser apresentadas na resposta à consulta. Entretanto, é bem provável que seja bem ine-
ficiente. Consideraremos como um SGBD realmente avalia as consultas em capítulos 
posteriores; por ora, nosso propósito é simplesmente explicar o significado de uma con-
sulta. Ilustraremos a estratégia de avaliação conceitual usando a seguinte consulta:
(C1) Encontre os nomes de marinheiros que reservaram o barco 103.
2 As expressões com NOTNOT sempre podem ser substituídas por expressões equivalentes sem NOTNOT dado o con-
junto de operadores de comparação listados.
■
■
■
■
116 CAPÍTULO 5
C1 pode ser expressa em SQL assim:
 SELECTSELECT M.nome-marin
 FROM FROM Marinheiros M, Reservas R
 WHEREWHERE M.id-marin = R.id-marin ANDAND R.id-barco= 103
Vamos computar a resposta a essa consulta nas instâncias R3 de Reservas e M4 de 
Marinheiros ilustradas nas Figuras 5.6 e 5.7, uma vez que a computação em nossas 
instâncias de exemplo usuais (R2 e M3) seriam desnecessariamente tediosas.
id-marin id-barco dia
22 101 10/10/96
58 103 11/12/96 
id-marin nome-marin avaliação idade
22 dustin 7 45,0
31 lubber 8 55,5
58 rusty 10 35,0
Figura 5.6 Instância R3 de Reservas. Figura 5.7 Instância M4 de Marinheiros.
A primeira etapa é construir o produto cartesiano M4 ¥ R3, que é ilustrado na 
Figura 5.8.
id-marin nome-marin avaliação idade id-marin id-barco dia
22 dustin 7 45,0 22 101 10/10/96
22 dustin 7 45,0 58 103 11/12/96
31 lubber 8 55,5 22 101 10/10/96
31 lubber 8 55,5 58 103 11/12/96
58 rusty 10 35,0 22 101 10/10/96
58 rusty 10 35,0 58 103 11/12/96
Figura 5.8 M4 ¥ R3.
A segunda etapa é aplicar a qualificação M.id-marin = R.id-marin ANDAND R.id-barco 
= 103. (Observe que a primeira parte dessa qualificação requer uma operação junção.) 
Essa etapa elimina todas, exceto a última linha da instância ilustrada na Figura 5.8. 
A terceira etapa é eliminar as colunas não desejadas; apenas nome-marin aparece na 
cláusula SELECTSELECT. Essa etapa nos fornece o resultado ilustrado na Figura 5.9, que é 
uma tabela com uma única coluna e, por coincidência, apenas uma linha.
nome-marin
Rusty
Figura 5.9 Resposta à consulta C1 sobre R3 e M4.
5.2.1 Exemplos de Consultas SQL Básicas
Apresentaremos agora diversas consultas de exemplo, muitas das quais foram expressas 
anteriormente em álgebra e cálculo relacional (Capítulo 4). Nosso primeiro exemplo 
SQL: Consultas, Restrições, Gatilhos 117
ilustra que o uso de variáveis de intervalo é opcional, a menos que elas sejam necessá-
rias para resolver uma ambigüidade. A Consulta C1, que discutimos na seção anterior, 
também pode ser expressa assim:
 SELECTSELECT nome-marin
 FROM FROM Marinheiros M, Reservas R
 WHEREWHERE M.id-marin = R.id-marin ANDAND R.id-barco= 103
Apenas as ocorrências de id-marin devem ser qualificadas, uma vez que essa colu-
na aparece em ambas as tabelas Marinheiros e Reservas. Uma forma equivalente de 
escrever esta consulta é:
 SELECTSELECT nome-marin
 FROM FROM Marinheiros, Reservas
 WHEREWHERE Marinheiros.id-marin = Reservas.id-marin ANDAND id-barco= 103
Essa consulta mostra que os nomes de tabelas podem ser usados implicitamente 
como variáveis de linha. As variáveis de intervalo precisam ser introduzidas explici-
tamente apenas quando a cláusula FROMFROM contiver mais que uma ocorrência de uma 
relação.3 Entretanto, recomendamos o uso explícito de variáveis de intervalo e a qua-
lificação completa de todas as ocorrências das colunas com uma variável de intervalo 
para melhorar a legibilidade de suas consultas. Adotaremos essa convenção em todos 
os nossos exemplos.
(C16) Encontre os id-marins dos marinheiros que reservaram um barco vermelho.
 SELECTSELECT R.id-marin
 FROM FROM Barcos B, Reservas R
 WHERE WHERE B.id-barco = R.id-barco ANDAND B.cor = ‘vermelho’
Essa consulta contém uma junção de duas tabelas, seguidas por uma seleção na 
cor dos barcos. Podemos considerar B e R como as linhas nas tabelas correspondentes 
que ‘demonstram’ que um marinheiro com id-marin R.id-marin reservou um barcovermelho B.id-barco. Em nossas instâncias de exemplo R2 e M3 (Figuras 5.1 e 5.2), a 
resposta consiste nos id-marins 22, 31 e 64. Se desejarmos os nomes dos marinheiros no 
resultado, deveremos também considerar a relação Marinheiros, uma vez que Reservas 
não contém essa informação, como ilustra o próximo exemplo.
(C2) Encontre os nomes dos marinheiros que reservaram um barco vermelho.
 SELECTSELECT M.nome-marin
 FROM FROM Marinheiros M, Reservas R, Barcos B
 WHEREWHERE M.id-marin = R.id-marin ANDAND R.id-barco = B.id-barco ANDAND B.cor = ‘vermelho’
Essa consulta contém uma junção das três tabelas seguidas por uma seleção na cor 
dos barcos. A junção com Marinheiros nos permite encontrar o nome do marinheiro 
que, de acordo com a tupla R de Reservas, reservou um barco vermelho descrito pela 
tupla B.
(C3) Encontre as cores dos barcos reservados por Lubber.
3 O nome da tabela não pode ser usado como uma variável de intervalo implícita, uma vez que uma variável 
de intervalo é introduzida para a relação.
118 CAPÍTULO 5
 SELECT SELECT B.cor
 FROM FROM Marinheiros M, Reservas R, Barcos B
 WHERE WHERE M.id-marin = R.id-marin ANDAND R.id-barco = B.id-barco ANDAND
 M.nome-marin = ‘Lubber’
Essa consulta é muito semelhante à anterior. Observe que, em geral, pode haver 
mais do que um marinheiro chamado Lubber (uma vez que nome-marin não é uma 
chave de Marinheiros); essa consulta ainda é correta, pois ela retornará as cores dos 
barcos reservados por algum Lubber, se houver diversos marinheiros chamados Lubber.
(C4) Encontre os nomes dos marinheiros que reservaram pelo menos um barco.
 SELECTSELECT M.nome-marin
 FROM FROM Marinheiros M, Reservas R
 WHEREWHERE M.id-marin = R.id-marin
A junção de Marinheiros e Reservas assegura que, para cada nome-marin selecio-
nado, o marinheiro tenha feito alguma reserva. (Se um marinheiro não tivesse feito 
uma reserva, a segunda etapa na estratégia de avaliação conceitual eliminaria todas as 
linhas no produto cartesiano que envolvessem esse marinheiro.)
5.2.2 Expressões e Strings no Comando SELECT
A SQL suporta uma versão mais genérica da lista-seleção do que apenas uma lista de 
colunas. Cada item em uma lista-seleção pode ser da forma expressão ASAS nome-coluna, 
onde expressão é qualquer expressão aritmética ou de string envolvendo os nomes de 
colunas (possivelmente prefixadas por variáveis de intervalo) e constantes, e nome-
coluna é um novo nome para essa coluna na saída da consulta. A lista-seleção também 
pode conter funções agregadas, tais como sum e count, que discutiremos na Seção 5.5. 
O padrão SQL também inclui expressões envolvendo valores de data e hora, os quais 
não trataremos. Embora não seja parte do padrão SQL, muitas implementações tam-
bém suportam o uso de funções embutidas como sqrt, sin e mod.
(C17) Compute incrementos das avaliações de pessoas que manobraram dois barcos 
diferentes no mesmo dia.
 SELECT SELECT M.nome-marin, M.avaliação+1 ASAS avaliação
 FROM FROM Marinheiros M, Reservas R1, Reservas R2
 WHERE WHERE M.id-marin = R1.id-marin ANDAND M.id-marin = R2.id-marin
 ANDAND R1.dia = R2.dia ANDAND R1.id-barco < > R2.id-barco
E, ainda, cada item em uma qualificação pode ser tão genérico quanto expressão1 
= expressão2.
 SELECT SELECT M1.nome-marin ASAS nome1, M2.nome-marin ASAS nome2
 FROM FROM Marinheiros M1, Marinheiros M2
 WHERE WHERE 2*M1.avaliação = M2.avaliação-1
Para comparações de string, podemos usar os operadores de comparação (=, <, > 
etc.) com a ordem das strings determinada alfabeticamente como usual. Se necessi-
tarmos ordenar strings em uma ordem que não seja alfabética (por exemplo, ordenar 
strings que denotam os nomes dos meses na ordem do calendário: Janeiro, Fevereiro, 
Março etc.), a SQL suporta um conceito genérico de collation, ou ordem de classifica-
ção, para um conjunto de caracteres. Uma collation permite que o usuário especifique 
lfilho
Retângulo
Encerra aqui o trecho do livro disponibilizado para 
esta Unidade de Aprendizagem. Na Biblioteca Virtual 
da Instituição, você encontra a obra na íntegra.

Mais conteúdos dessa disciplina