Prévia do material em texto
C. J. Date
Novatec
SQL e
Teoria Relacional
Como escrever códigos SQL precisos
Authorized Portuguese translation of the English edition of titled SQL and Relational Theory 2E ISBN
9781449316402 © 2012 C. J. Date. This translation is published and sold by permission of O'Reilly Media,
Inc., the owner of all rights to publish and sell the same.
Tradução em português autorizada da edição em inglês da obra SQL and Relational Theory 2E ISBN
9781449316402 © 2012 C. J. Date. Esta tradução é publicada e vendida com a permissão da O'Reilly Media,
Inc., detentora de todos os direitos para publicação e venda desta obra.
© Novatec Editora Ltda. [2015].
Todos os direitos reservados e protegidos pela Lei 9.610 de 19/02/1998.
É proibida a reprodução desta obra, mesmo parcial, por qualquer processo, sem prévia autorização, por escrito,
do autor e da Editora.
Editor: Rubens Prates
Tradução: Rafael Zanolli
Revisão técnica: Edgard Damiani / Rodrigo Stulzer
Revisão gramatical: Marta Almeida de Sá
Editoração eletrônica: Carolina Kuwabata
Assistente editorial: Priscila A. Yoshimatsu
ISBN: 978-85-7522-433-5 MP20150506
Histórico de impressões:
Maio/2015 Primeira edição
Novatec Editora Ltda.
Rua Luís Antônio dos Santos 110
02460-000 – São Paulo, SP – Brasil
Tel.: +55 11 2959-6529
Fax: +55 11 2950-8869
Email: novatec@novatec.com.br
Site: www.novatec.com.br
Twitter: twitter.com/novateceditora
Facebook: facebook.com/novatec
LinkedIn: linkedin.com/in/novatec
Nutshell Handbook, o logotipo Nutshell Handbook e o logotipo da O’Reilly são marcas registradas da O’Reilly
Media, Inc.
SQL e Teoria Relacional: Como Escrever Códigos SQL Precisos e os elementos comerciais relacionados são
marcas registradas da O’Reilly Media, Inc.
Muitas das designações usadas por fabricantes e vendedores para distinguir seus produtos são marcas regis-
tradas. Nos locais em que termos desse tipo foram utilizados neste livro, estando a O’Reilly Media, Inc. ciente
da existência de uma marca registrada, as designações foram escritas em letras maiúsculas ou com a letra
inicial maiúscula.
Ainda que todas as precauções tenham sido tomadas na preparação deste livro, a editora e os autores não se
responsabilizam por erros, omissões ou danos que resultem do uso das informações contidas neste texto.
23
capítulo 1
Preparando o cenário
Senta-te pacientemente, minha alma;
Não julgues antes de apresentada a peça;
Seu enredo tem muitas variações; cada dia
Traz uma nova cena; o último ato coroa a peça.
– Francis Quarles: Emblemas (1635)
Uma abordagem relacional à linguagem SQL: esse é o tema – ou um dos temas –
deste livro. Evidentemente, para tratar de tal tópico adequadamente, preciso abordar
questões relacionais assim como questões de SQL em si – e ainda que essa afirmação
obviamente se aplique ao livro como um todo, ela se aplica ao primeiro capítulo com
força especial. Em consequência, este capítulo tem comparativamente pouco a dizer
sobre SQL como tal. O que desejo fazer é revisar material que, na sua maior parte,
espero que, de qualquer maneira, você já conheça. Minha intenção é estabelecer um
ponto de partida como tal: em outras palavras, estabelecer algumas bases sobre as
quais o restante do livro possa ser construído. No entanto, ainda que eu espere que
você esteja familiarizado com a maioria do que tenho a dizer neste capítulo, gostaria
de sugerir, respeitosamente, que você não o pule. Você precisa saber o que precisa
saber (se entende o que eu quero dizer); mais especificamente, você precisa ter certeza
de que tem os pré-requisitos necessários para compreender o material que virá nos
capítulos futuros. Na realidade, gostaria de recomendar educadamente que, ao longo
deste livro, você não pule a discussão de algum assunto só porque acredita que já
esteja familiarizado com o tópico. Por exemplo, você tem certeza de que sabe o que
é uma chave, em termos relacionais? Ou uma junção?1
1 Existe pelo menos um especialista que não sabe. A seguir temos uma citação direta de um docu-
mento que afirma (como este livro!) oferecer conselhos para usuários SQL: “Não utilize junções
... Oracle e SQL Server têm abordagens fundamentalmente diferentes sobre esse conceito ... Você
pode terminar com conjuntos de resultado inesperados ... Você deve compreender os tipos básicos
de cláusulas de junções ... Junções equivalentes são formadas recuperando todos os dados de
duas fontes distintas e combinando-os em uma grande tabela ... Junções internas são feitas nas
colunas internas de duas tabelas. Junções externas são feitas nas colunas externas de duas tabelas.
Junções à esquerda são feitas nas colunas à esquerda de duas tabelas. Junções à direita são feitas
nas colunas à direita de duas tabelas.”
SQL e Teoria Relacional24
O modelo relacional é muito mal-compreendido
Profissionais em qualquer disciplina precisam conhecer os fundamentos de seu
campo. Por isso, se você é um profissional de bancos de dados, precisa conhecer o
modelo relacional, pois o modelo relacional é a base (ou uma grande parte da base,
de qualquer modo) do campo dos bancos de dados em particular. Agora, todo curso
em gerenciamento de bancos de dados, seja ele acadêmico ou comercial, realmente
manifesta pelo menos a ideia de ensinar o modelo relacional – mas a maioria desse
ensino parece ser feita de modo muito equivocado, se tivermos por base os resultados.
Certamente, o modelo não é bem entendido pela comunidade de bancos de dados
como um todo. Aqui estão alguns dos possíveis motivos para essa situação atual:
• O modelo é ensinado em um vácuo. Ou seja, pelo menos para principiantes, é
difícil ver a relevância do material, entender os problemas que ele deve resolver,
ou ambos.
• Os próprios instrutores não entendem completamente ou não apreciam a
significância do material.
• Talvez, mais provavelmente na prática, o modelo não seja sequer ensinado – a
linguagem SQL, ou algum dialeto específico dessa linguagem, como o dialeto
Oracle, é ensinado em vez disso.
Então este livro é direcionado aos praticantes de bancos de dados em geral, e aos pra-
ticantes de SQL em particular, que já tiveram alguma exposição ao modelo relacional,
mas que não sabem tanto sobre ele quanto deveriam, ou gostariam de saber. Este
livro definitivamente não é para iniciantes; no entanto, ele também não é apenas um
curso para refrescar sua memória. Para ser mais específico, estou certo de que você
sabe algo sobre SQL; mas – e peço desculpas pelo tom possivelmente ofensivo aqui –
se o seu conhecimento do modelo relacional deriva apenas de seu conhecimento de
SQL, temo que você não conheça o modelo relacional tão bem como deveria e que
provavelmente “saiba algo que não sabe”. Não tenho como enfatizar isso o suficiente:
SQL e o modelo relacional não são iguais. Aqui, para ilustrar, estão algumas questões
relacionais sobre as quais a SQL não é tão clara (para dizer o mínimo):
• O que são realmente bancos de dados, relações e tuplas.
• A diferença entre valores de relação e variáveis de relação.
• A relevância de predicados e proposições.
• A importância de nomes de atributos.
• A função crucial de restrições de integridade.
• O princípio da informação e seu significado.
25Capítulo 1 ■ Preparando o cenário
E assim por diante (essa não é uma lista completa). Todas essas questões, e muitas
outras, são abordadas neste livro.
Digo novamente: se o seu conhecimento do modelo relacional deriva apenas de
seu conhecimento de SQL, então pode ser que você “saiba algo que não sabe”. Uma
consequência é que você poderá perceber, lendo este livro, que terá de desaprender
um pouco – e desaprender, infelizmente, é algo muito difícil.
Algumas observações sobre terminologia
Provavelmente você percebeu de imediato, na lista de itens de questões relacionais
da seção anterior, que utilizei os termos formais relação, tuplas e atributo. A SQL não
usa esses termos, é claro – ela utiliza, em vez disso, os termos mais “amigáveis” tabela,
linha e coluna. E,antigo de S foi totalmente subs-
tituído por um novo valor. Evidentemente, o valor antigo (com cinco tuplas) e o novo
(com quatro) são bastante semelhantes em certo sentido, mas eles definitivamente
são valores distintos. Aliás, o DELETE que acabamos de mostrar é logicamente equi-
valente, e, na realidade, uma abreviação da atribuição relacional que vemos a seguir:
S := S MINUS ( S WHERE CITY = 'Athens' ) ;
Assim como em todas as atribuições, o efeito aqui é que (a) a expressão de origem no
lado direito é avaliada e, daí, (b) o valor que é o resultado dessa avaliação é, então,
atribuído à variável-alvo no lado esquerdo, com o resultado geral já explicado.
Nota paralela: não posso demonstrar a afirmação precedente em SQL porque
a SQL não suporta diretamente uma atribuição relacional. Em vez disso, de-
monstrei essa afirmação (assim como o DELETE original) em uma linguagem
mais ou menos autoexplicativa chamada Tutorial D. Tutorial D é a linguagem
SQL e Teoria Relacional50
que Hugh Darwen e eu usamos para ilustrar ideias relacionais em nosso livro
Databases, Types, and the Relational Model: The Third Manifesto (veja o apêndice
G) – e também vou usá-la no presente livro, quando estiver explicando conceitos
relacionais15. Contudo, uma vez que meu público-alvo seja os praticantes de
SQL, também vou, na maioria dos casos, mostrar os análogos em SQL. Nota:
uma gramática BNF para a Tutorial D pode ser encontrada no apêndice D.
Fim da nota paralela.
Para repetir, DELETE é a abreviação para uma determinada atribuição relacional – e,
é claro, uma observação análoga se aplica também a INSERT e UPDATE: eles também
são basicamente apenas abreviações para determinadas atribuições relacionais. Dessa
forma, como mencionei na seção “Uma revisão do modelo original”, a atribuição rela-
cional é o operador de atualização fundamental no modelo relacional; de fato, ela é
o único operador de atualização de que realmente precisamos, logicamente falando.
Assim, há uma diferença lógica entre valores de relação e variáveis de relação. O
problema é que a literatura de bancos de dados tem historicamente usado o mesmo
termo, relação, para significar ambos, e essa prática certamente levou à confusão16.
Neste livro, portanto, vou distinguir muito cuidadosamente entre os dois daqui em
diante – falarei em termos de valores de relação quando quiser dizer valores de rela-
ção, e em variáveis de relação quando quiser dizer variáveis de relação. No entanto,
também vou, na maioria dos casos, abreviar valor de relação como apenas relação
(exatamente como abreviamos, na maioria dos casos, valor inteiro como apenas inteiro).
E vou abreviar variável de relação, na maioria dos casos, como relvar; por exemplo,
direi que o banco de dados de fornecedores e peças contém três relvars (mais preci-
samente, três relvars de base).
Como um exercício, você pode se interessar por revisar o texto deste capítulo até
aqui e verificar exatamente onde usei o termo relação quando na realidade deveria
ter usado, em vez disso (ou também), o termo relvar.
Valores e variáveis
A diferença lógica entre relações e relvars é, na realidade, um caso especial de diferen-
ça lógica entre valores e variáveis em geral, e gostaria de dedicar alguns momentos
15 Vários revisores reclamaram desse fato – isto é, sentiam que eu deveria utilizar a própria SQL, e
não alguma linguagem não padronizada como a Tutorial D, para ilustrar ideias relacionais. (Um
até sugeriu que o livro fosse renomeado “Tutorial D e teoria relacional”!) Mas a SQL como tal
nunca foi pretendida como um veículo para ilustração de ideias relacionais, enquanto a Tutorial D
explicitamente o foi; e, de qualquer modo, a SQL simplesmente não é adequada à tarefa. De fato,
se ela o fosse, um livro como este não seria necessário, em primeiro lugar.
16 A SQL comete o mesmo erro, é claro, pois ela também tem apenas um termo, tabela, que deve ser
entendido como, às vezes, significando um valor de tabela e, em outros casos, uma variável de tabela.
51Capítulo 1 ■ Preparando o cenário
para analisar o caso de forma geral. (Essa é uma leve digressão, mas penso que vale a
pena dedicar o tempo aqui, pois um raciocínio claro nessa área pode ser – de muitas
maneiras – de grande ajuda). Aqui estão, portanto, algumas definições:
Definição: um valor é o que os especialistas em lógica chamam de uma “cons-
tante individual”, como o inteiro 3. Um valor não tem localização no tempo e
no espaço. Entretanto, valores podem ser representados na memória por meio
de alguma codificação, e essas representações ou codificações realmente têm
uma localização no tempo e no espaço. De fato, representações distintas do
mesmo valor podem aparecer em um número variado de localizações distintas
no tempo e no espaço – significando, livremente, que um número qualquer
de variáveis distintas (veja a próxima definição) pode ter o mesmo valor, ao
mesmo tempo ou em momentos distintos. Observe em particular que, por
definição, um valor não pode ser atualizado; pois, se pudesse, então depois de
tal atualização ele não seria mais esse valor.
Definição: uma variável é uma detentora de uma representação de um valor.
Uma variável tem localização no tempo e no espaço. Além disso, variáveis, di-
ferentemente de valores, podem ser atualizadas; isto é, o valor atual da variável
pode ser substituído por outro valor. (Afinal, é isso que “variável” significa – ser
uma variável significa ser atualizável, e ser atualizável significa ser uma variável;
de modo equivalente, ser uma variável significa ser atribuível, e ser atribuível
significa ser uma variável.)
Por favor, observe com atenção que não são apenas elementos como o inteiro 3 que
são valores legítimos. Pelo contrário, valores podem ser arbitrariamente complexos –
por exemplo, um valor pode ser um ponto geométrico; ou um polígono; ou um raio
X; ou um documento XML; ou uma impressão digital; ou um array; ou uma pilha;
ou uma lista; ou uma relação (e assim por diante). Observações análogas também se
aplicam às variáveis, é claro. Terei mais a dizer sobre tais assuntos no próximo capítulo.
Agora, você pode pensar que é difícil imaginar pessoas se confundindo com uma
distinção tão óbvia e fundamental como a que existe entre valores e variáveis. Na
realidade, no entanto, é bastante fácil cair em armadilhas nessa área. Como uma
forma de ilustração, considere o trecho a seguir, retirado de um tutorial sobre bancos
de dados de objetos (as porções em itálico dentro das chaves são comentários feitos
por mim mesmo):
Distinguimos o tipo declarado de uma variável... do tipo do objeto que é o
valor atual da variável [então um objeto é um valor]... Distinguimos objetos
de valores [então um objeto não é um valor afinal de contas]... Um modifi-
cador [é um operador de tal modo que é] possível observar seu efeito em
algum objeto [então, na realidade, um objeto é uma variável].
SQL e Teoria Relacional52
Observações de encerramento
Isso nos traz ao final deste capítulo preliminar. Na maior parte, meu objetivo tem sido
apenas lhe dizer o que espero que você já saiba (e você pode, portanto, ter sentido
que o capítulo foi um pouco leve em substância técnica). De qualquer forma, apenas
para revisar brevemente:
• Expliquei porque estaríamos preocupados com princípios, e não produtos, e
porque vou usar a terminologia formal, como relação, tupla e atributo (pelo menos
em contextos relacionais) – em vez de suas contrapartes SQL mais amigáveis.
• Ofereci uma visão geral do modelo original, abordando, em particular, estes
conceitos: tipo (ou domínio), relação de grau n, tuplas, atributo, chave candidata
(chave, para abreviar), chave primária, chave estrangeira, integridade de entida-
de, integridade referencial, atribuição relacional e a álgebra relacional. (Também
mencionei brevemente o cálculo relacional.) Com respeito à álgebra, mencionei
a propriedade de fechamento e descrevi muito brevemente os operadores de
restrição, projeção, produto,intersecção, união, diferença e junção.
• Discuti várias propriedades das relações, apresentando os termos cabeçalho,
corpo, cardinalidade e grau. Relações não têm tuplas duplicadas, nenhuma
ordenação de tuplas de cima para baixo e nenhuma ordenação de atributos
da esquerda para a direita. Também discuti as diferenças entre relações de base
(ou relvars de base, na realidade) e visões. E expliquei que todo subconjunto de
uma tupla é uma tupla, todo subconjunto de um cabeçalho é um cabeçalho e
todo subconjunto de um corpo é um corpo.
• Discuti as diferenças lógicas entre modelo e implementação, valores e variáveis em
geral, e relações e relvars em particular. A discussão de modelo versus implementação,
em particular, levou-nos a uma discussão sobre independência de dados físicos.
• Afirmei que a SQL e o modelo relacional não representam o mesmo conceito.
Já vimos algumas diferenças – por exemplo, o fato de que a SQL permite linhas
duplicadas, de que tabelas SQL têm uma ordenação de colunas da esquerda
para a direita e de que a SQL não distingue entre valores de tabela e variáveis
de tabela – e veremos muitas outras nas páginas seguintes.
Um último ponto (não mencionei isso explicitamente antes, mas espero que esteja
claro a partir de tudo que disse): em geral, o modelo relacional é declarativo, e não
procedural, por natureza; ou seja, ele sempre favorece soluções declarativas em vez
de soluções procedurais, sempre que tais soluções sejam viáveis. A razão é óbvia:
declarativo significa que o sistema faz o trabalho, procedural significa que o usuário
faz o trabalho (então, estamos falando sobre produtividade, dentre outros conceitos).
É por isso que o modelo relacional suporta consultas declarativas, atualizações
53Capítulo 1 ■ Preparando o cenário
declarativas, definições de visão declarativas, restrições de integridade declarativas
e assim por diante.
Nota: depois de ter escrito o parágrafo anterior pela primeira vez, fui informado de que
pelo menos um produto SQL bem conhecido aparentemente utiliza o termo “declarativo”
para significar que o sistema não faz o trabalho! Isto é, ele permite que o usuário faça
certas afirmações declarativamente (por exemplo, o fato de uma determinada visão ter
uma determinada chave), mas não obriga a restrição indicada por essa declaração – ele
simplesmente presume que o usuário irá obrigá-la. Tais abusos terminológicos fazem
pouco para ajudar a causa do entendimento genuíno. Caveat lector.
Exercícios
1.1 (Retirado do corpo do capítulo, mas levemente reescrito aqui.) Se você ainda não o
fez, verifique o capítulo novamente e identifique todos os locais em que usei o termo
relação e deveria, por direito, ter usado o termo relvar, em vez disso.
1.2 Quem foi E. F. Codd?
1.3 O que é um domínio?
1.4 O que você entende pelo termo integridade referencial?
1.5 Os termos cabeçalho, corpo, atributo, tupla, cardinalidade e grau, definidos no corpo
do capítulo para valores de relação, podem ser todos interpretados da forma óbvia
para se aplicar também a relvars. Procure entender essa observação.
1.6 Faça a distinção entre os dois significados do termo modelo de dados.
1.7 Explique, com suas próprias palavras, (a) independência de dados físicos e (b)
a diferença entre modelo e implementação.
1.8 No corpo do capítulo, eu disse que tabelas como aquelas das figuras 1.1 e 1.3 não
eram relações como tais, mas, em vez disso, imagens de relações. Quais são alguns dos
pontos de diferença específicos entre essas imagens e as relações correspondentes?
1.9 (Tente este exercício sem revisar o corpo do capítulo.) Quais relvars o banco de dados
de fornecedores e peças contém? Que atributos elas envolvem? Que chaves e chaves
estrangeiras elas têm? (O sentido deste exercício é que vale a pena se tornar o mais
familiarizado possível com a estrutura, pelo menos em termos gerais, do exemplo
corrente. Não é tão importante lembrar-se detalhadamente dos valores dos dados
em si – ainda que não seja má ideia lembrar-se deles.)
1.10 “Existe apenas um modelo relacional.” Explique essa afirmação.
1.11 A seguir, temos um trecho retirado de certo livro teórico de bancos de dados: “É
importante fazer uma distinção entre relações armazenadas, que são tabelas, e relações
SQL e Teoria Relacional54
virtuais, que são visões... Utilizaremos relação apenas onde uma tabela ou visão puder
ser utilizada. Quando quisermos enfatizar que uma relação está armazenada, em vez
de uma visão, vamos, às vezes, utilizar o termo relação de base ou tabela de base.” Esse
texto revela várias confusões e equívocos com relação ao modelo relacional. Identi-
fique tantos quantos você puder.
1.12 A seguir, temos um trecho retirado de outro livro teórico de bancos de dados:
“O modelo relacional (...) define tabelas simples para cada relação e relacionamentos
muitos-para-muitos. Chaves de referência cruzada ligam as tabelas, representando os
relacionamentos entre as entidades. Índices primários e secundários fornecem acesso
rápido aos dados com base em qualificações.” Pretende-se que esse texto seja uma
definição (!) do modelo relacional... O que há de errado nele?
1.13 Escreva instruções CREATE TABLE para uma versão SQL do banco de dados
de fornecedores e peças.
1.14 A seguir temos uma típica instrução SQL INSERT no banco de dados de for-
necedores e peças:
INSERT INTO SP ( SNO , PNO , QTY ) VALUES ( 'S5' , 'P6' , 250 ) ;
Mostre uma operação de atribuição relacional equivalente. Nota: reconheço que
ainda não expliquei a sintaxe da atribuição relacional detalhadamente, por isso não
se preocupe tanto em fornecer uma resposta sintaticamente correta – apenas faça o
melhor que puder.
1.15 (Mais difícil.) A seguir temos uma típica instrução SQL UPDATE no banco de
dados de fornecedores e peças:
UPDATE S SET STATUS = 25 WHERE CITY = 'Paris' ;
Mostre uma operação de atribuição relacional equivalente. (O propósito deste exer-
cício é fazer você pensar sobre o que está envolvido. Ainda não lhe disse o suficiente
neste capítulo para permitir que você o responda completamente. Veja as discussões
sobre consultas “e se” no capítulo 7 para uma explicação detalhada.)
1.16 Ao longo do capítulo, eu disse que a SQL não suporta diretamente a atribuição
relacional. Ele a suporta indiretamente? Se afirmativo, de que forma? Uma questão re-
lacionada: podem todas as atribuições relacionais ser expressas em termos de INSERT
e/ou DELETE e/ou UPDATE? Se negativo, por que não? Quais são as implicações?
1.17 De um ponto de vista prático, por que você acha que tuplas duplicadas, ordena-
ção de tuplas de cima para baixo e ordenação de atributos da esquerda para a direita
são todas ideias muito ruins? (Essas questões deliberadamente não foram respondidas
ao longo do capítulo, e este exercício pode servir melhor como uma base para dis-
cussões em grupo. Analisaremos mais de perto tais questões futuramente no livro.)em geral, sou simpático à ideia de usar termos mais amigáveis, se
eles podem ajudar a tornar as ideias mais palatáveis. No caso presente, entretanto,
parece-me que, infelizmente, eles não tornam as ideias mais palatáveis; em vez disso,
eles as distorcem e, na realidade, prestam um grande desserviço à causa do entendi-
mento genuíno. A verdade é que uma relação não é uma tabela, uma tupla não é uma
linha e um atributo não é uma coluna. E ainda que possa ser aceitável fingirmos o
contrário em contextos informais – de fato, eu mesmo muitas vezes faço isso –, diria
que isso é aceitável apenas se todos entenderem que os termos mais amigáveis ao
usuário são apenas uma aproximação da verdade e que falham, no sentido geral, em
capturar a essência do que está realmente acontecendo. Colocando de outra forma:
se você entende a situação real, então o uso criterioso de termos amigáveis pode ser
uma boa ideia; mas para aprender e apreciar a situação real, em primeiro lugar, você
realmente precisa entender os termos formais. Neste livro, portanto, tenderei a usar
esses termos formais (pelo menos quando estiver falando sobre o modelo relacional,
em vez de SQL) e darei definições precisas para eles no momento relevante. Em con-
textos SQL, por contraste, usarei os termos da própria SQL.
E outro ponto sobre terminologia. Tendo dito que a SQL tenta simplificar um con-
junto de termos, devo também dizer que ela faz tudo que pode para complicar outros.
Refiro-me ao seu uso dos termos operador, função, procedimento, rotina e método – todos
os quais denotam essencialmente o mesmo elemento (com, talvez, diferenças muito
pequenas). Neste livro, utilizarei o termo operador em todo o texto; portanto, vou me
referir, por exemplo, a “=” (comparação de igualdade), “:=” (atribuição), “+” (adição),
DISTINCT, JOIN, SUM, GROUP BY (etc., etc.), todos especificamente como operadores.
Falando sobre SQL, incidentalmente, deixe-me lembrá-lo de que (como foi dito no
prefácio) uso esse termo para representar exclusivamente a versão padrão da lingua-
gem, exceto em alguns locais em que o contexto exige o contrário2. Entretanto:
2 O padrão tem passado por várias versões, ou edições, ao longo dos anos. A versão atual quando
da redação deste texto é SQL:2008 (para a qual uma referência formal pode ser encontrada no
SQL e Teoria Relacional26
• O uso padronizado da terminologia às vezes não é muito adequado. Em tais
situações, geralmente prefiro utilizar minha própria terminologia. Por exemplo,
uso o termo expressão de tabela em vez do termo padrão expressão de consulta
por estes motivos, dentre outros: primeiro, o valor que tais expressões denotam
é realmente uma tabela e não uma consulta; segundo, consultas, de qualquer
forma, não são o único contexto em que tais expressões são utilizadas. (Na
realidade, o padrão de fato utiliza o termo expressão de tabela, mas, uma vez
mais, ele o faz de modo inapropriado; para ser específico, ele o utiliza para se
referir ao que vem depois da cláusula SELECT em uma expressão SELECT.)
• Dando continuidade ao ponto anterior, devo acrescentar que nem todas as
expressões de tabela – seja em meu sentido ou no sentido padronizado – são
válidas em SQL em todos os contextos em que poderíamos esperar que elas o
fossem. Em particular, uma invocação JOIN específica, ainda que certamente
denote uma tabela, não pode aparecer como uma expressão de tabela “inde-
pendente” (isto é, no nível mais externo de aninhamento), nem pode aparecer
como a expressão de tabela entre parênteses que constitui uma subconsulta
(veja o capítulo 12)3. Por favor, note que essas afirmações se aplicam a muitas das
discussões individuais do corpo do livro; no entanto, seria muito tedioso as seguir
repetindo, e eu não o farei. (Entretanto, elas são refletidas na gramática BNF no
capítulo 12.)
• Neste livro, ignoro aspectos do padrão que poderiam ser considerados como
esoterismo barato – especialmente se não fizerem parte do que o padrão chama
de “Core SQL” ou se não tiverem muita relação com processamento relacional
como tal. Exemplos aqui incluem as funções chamadas analíticas ou de janela
(OLAP); SQL dinâmico; tabelas temporárias; e detalhes de tipos definidos
pelo usuário.
• Por motivos que não são importantes aqui, utilizo um estilo para comentários
que difere daquele do padrão. Para ser específico, mostro comentários como
strings de texto em itálico, entre delimitadores “/*” e “*/”.
Esteja ciente, no entanto, de que todos os produtos SQL incluem funcionalidades que
não são parte do padrão em si. IDs de linhas fornecem um exemplo comum. Meu
conselho geral a respeito de tais funcionalidades é: utilize-as, se desejar – mas não se
elas violarem princípios relacionais (afinal, estou defendendo o que deveria ser uma
abordagem relacional à SQL). Por exemplo, IDs de linha, em particular, provavelmente
violam o Princípio da intercambialidade (veja o capítulo 9), o Princípio da informação
apêndice G); a versão anterior era SQL:2003, antes dessa, SQL:1999; e a anterior a essa, SQL:1992.
A maioria das funcionalidades SQL discutidas neste livro estava presente na SQL:1992, e muitas
vezes até em versões anteriores.
3 Essas limitações particulares foram adicionadas no padrão SQL:2003; elas não se aplicavam ao
SQL:1992, que é onde invocações JOIN explícitas foram primeiro apresentadas, nem ao SQL:1999.
27Capítulo 1 ■ Preparando o cenário
(veja o apêndice A) ou ambos; e se o fizerem, então eu certamente não os utilizaria.
No entanto, aqui e em todos os locais, a regra suprema é: você pode fazer o que quiser,
desde que saiba o que está fazendo.
Princípios, não produtos
Vale parar por um momento para analisar a questão de por que, como eu disse antes,
você, como um profissional de bancos de dados, precisa conhecer o modelo relacional.
O motivo é que o modelo relacional não é específico a produtos; em vez disso, ele
se preocupa com princípios. O que quero dizer com princípios? Bem, aqui está uma
definição (do Chambers Twentieth Century Dictionary):
princípio: uma fonte, raiz, origem: aquilo que é fundamental: essencial
em natureza: base teórica: uma verdade fundamental a qual outras têm
por base ou da qual se originam.
O ponto sobre princípios é: eles perduram. Por contraste, produtos e tecnologias (e
a linguagem SQL, nesse sentido) mudam o tempo todo – mas princípios não. Por
exemplo, vamos supor que você conheça Oracle; aliás, suponha que você seja um
especialista em Oracle. Mas se Oracle é tudo que você conhece, então seu conheci-
mento não é necessariamente transferível para, digamos, um ambiente DB2 ou SQL
Server (ele pode até dificultar o progresso nesse novo ambiente). Contudo, se você
conhece os princípios subjacentes – em outras palavras, se você conhece o modelo
relacional –, você tem conhecimentos e habilidades que serão transferíveis: conheci-
mentos e habilidades que você poderá aplicar em todos os ambientes e que nunca
serão obsoletos.
Neste livro, portanto, estaremos preocupados com princípios, não produtos, e fun-
damentos, não tendências ou modismos. Porém eu realmente percebo que, às vezes,
você tem de fazer compromissos e concessões no mundo real. Como um exemplo, às
vezes você pode ter boas razões pragmáticas para não projetar o banco de dados de
modo teoricamente ótimo. Como outro exemplo, considere a SQL novamente. Ainda
que certamente seja possível utilizar SQL relacionalmente (na maioria dos casos, de
qualquer modo), às vezes você perceberá – porque implementações existentes estão
longe de serem perfeitas – que existem severas penalidades de desempenho em fazê-
-lo... caso em que você pode ser mais ou menos forçado a fazer algo não “verdadei-
ramente relacional” (como escrever uma consulta de modo não natural para obrigar
a implementação a usar um índice). No entanto, acredito firmemente que você deva
sempre assumir esses compromissos e concessões a partir de uma posição de força
conceitual. Ou seja:
• Você deve compreender o queestá fazendo quando decide assumir tal com-
promisso.
SQL e Teoria Relacional28
• Você deve saber qual é a situação teoricamente correta e deve ter fortes motivos
para se afastar dela.
• Você também deve documentar esses motivos, para que, caso eles deixem de
ser válidos em algum momento futuro (por exemplo, em razão de um novo
lançamento do produto utilizado fazer um trabalho melhor em algum sentido),
possa ser possível abandonar o compromisso original.
A citação a seguir – que é atribuída a Leonardo da Vinci (1452-1519) e tem, portanto,
aproximadamente 500 anos de idade – resume a situação admiravelmente:
Aqueles que se enamoram da prática sem a teoria são como um navegador
que entra em um navio sem leme nem bússola, que jamais tem certeza
para onde vai. Sempre a prática deve ser edificada sobre um conhecimento
sólido de teoria.
(Está bem, o itálico fui eu que acrescentei.)
Uma revisão do modelo original
O propósito desta seção é servir como um pontapé inicial para discussões subse-
quentes; ela revisa alguns dos aspectos mais básicos do modelo relacional como
originalmente definido. Note esse qualificador – “como originalmente definido”!
Um dos equívocos mais difundidos sobre o modelo relacional é o de que ele é algo
totalmente estático. Ele não é. Ele é, nesse sentido, como a matemática: a matemática
também não é algo estático, mas muda ao longo do tempo. Na realidade, o modelo
relacional pode, ele mesmo, ser visto como um pequeno ramo da matemática; como
tal, ele evolui ao longo do tempo, à medida que novos teoremas são provados e novos
resultados são descobertos. Além disso, essas novas contribuições podem ser feitas
por qualquer pessoa que seja competente para fazê-lo; assim como outros ramos da
matemática, o modelo relacional, ainda que tenha sido originalmente inventado por
um homem, tornou-se um esforço comunitário e agora pertence ao mundo.
Por falar nisso, caso você não saiba, esse homem foi E. F. Codd, na época, pesquisa-
dor da IBM (E de Edgar e F de Frank – mas ele sempre assinava com suas iniciais;
para seus amigos, entre os quais tenho orgulho em me incluir, ele era Ted). Foi no
final de 1968 que Codd, um matemático por treinamento, primeiro percebeu que a
disciplina da matemática poderia ser utilizada para injetar princípios sólidos em um
campo, o gerenciamento de bancos de dados, que antes era bastante deficiente em tais
qualidades. Sua definição original do modelo relacional apareceu em um relatório de
pesquisa da IBM em 1969; falarei mais sobre esse texto no apêndice G.
29Capítulo 1 ■ Preparando o cenário
Características estruturais
O modelo original tinha três componentes principais – estrutura, integridade e
manipulação; descreverei brevemente um de cada vez. Por favor, note de imediato,
no entanto, que todas as “definições” que darei são bastante genéricas; eu as tornarei
mais precisas à medida que e quando for apropriado em capítulos futuros.
Em primeiro lugar, então, estrutura. A principal característica estrutural é, evidente-
mente, a relação em si, e como todos sabem é comum desenharmos tais relações no
papel como tabelas (veja a figura 1.1 para um exemplo autoexplicativo). Relações são
definidas por tipos (também conhecidos como domínios); um tipo é basicamente um
acervo conceitual de valores a partir dos quais atributos efetivos, em relações efetivas,
assumem seus valores efetivos. Com referência, por exemplo, ao simples banco de
dados de departamentos (departments) e funcionários (employees) da figura 1.1 pode
haver um tipo chamado DNO (“números de departamentos”), que é o conjunto de
todos os números de departamentos válidos, e daí o atributo chamado DNO na
relação DEPT e o atributo chamado DNO na relação EMP conteriam valores desse
acervo conceitual. (Por falar nisso, não é necessário – ainda que, muitas vezes, seja
uma boa ideia – que atributos tenham o mesmo nome do tipo correspondente, e,
frequentemente, eles não o terão. Veremos muitos contraexemplos futuramente.)
Figura 1.1 – Valores de exemplo do banco de dados de departamentos e funcionários.
Como disse, tabelas como aquela da figura 1.1 representam relações: relações de grau
n, para sermos precisos. Uma relação de grau n pode ser imaginada como uma tabela
com n colunas; as colunas nessa figura representam atributos da relação e as linhas
representam tuplas. O valor n pode ser qualquer inteiro não negativo. Uma relação de
grau 1 é dita como sendo unária; uma relação de grau 2 é dita binária; uma relação
de grau 3, ternária; e assim por diante.
O modelo relacional também suporta vários tipos de chaves. Para começar – e esse
ponto é crucial! –, toda relação tem pelo menos uma chave candidata4. Uma chave
candidata é apenas um identificador exclusivo; em outras palavras, ela é uma combi-
nação de atributos – muitas vezes, mas nem sempre, uma “combinação” consistindo
4 Estritamente falando, essa frase deveria dizer “Cada relvar tem pelo menos uma chave candidata” (veja
a seção “Relações versus relvars”, mais adiante). Nota: na realidade, uma afirmação similar também
se aplica em outro ponto deste capítulo. O exercício 1.1 ao final do capítulo trata dessa questão.
SQL e Teoria Relacional30
de apenas um único atributo –, de tal modo que toda tupla na relação tenha um valor
exclusivo para a combinação em questão. Na figura 1.1, por exemplo, todo departamen-
to tem um número de departamento exclusivo e todo funcionário tem um número
de funcionário exclusivo, de modo que podemos dizer que {DNO} é uma chave
candidata para DEPT e {ENO} é uma chave candidata para EMP. A propósito, repare
nos caracteres de chaves de abertura e de fechamento; repetindo: chaves candidatas
são sempre combinações, ou conjuntos, de atributos (mesmo quando o conjunto em
questão contém apenas um atributo), e a representação convencional de um conjunto
no papel é uma lista de elementos, separados por vírgulas, entre caracteres de chaves.
Nota paralela: essa é a primeira vez que mencionei a expressão lista separada
por vírgulas, mas vou utilizá-la bastante em páginas futuras. Ela pode ser
definida desta forma: deixe que xyz seja algum construto 5 sintático (por
exemplo, “nome de atributo”). Então a expressão lista separada por vírgulas
xyz denota uma sequência de zero ou mais xyzs na qual cada par de xyzs
adjacentes é separado por uma vírgula (assim como, opcionalmente, por
um ou mais espaços antes ou depois da vírgula, ou em ambas as posições).
Por exemplo, se A, B e C forem nomes de atributos, então todos os exem-
plos a seguir serão listas separadas por vírgulas de nomes de atributos:
A , B , C
C , A , B
B
A , C
Assim também é a sequência vazia de nomes de atributos.
Além disso, quando alguma lista separada por vírgulas é colocada entre
caracteres de chaves e, portanto, denota um conjunto, então (a) a ordem
em que os elementos são mostrados dentro dessa lista é imaterial (pois
conjuntos não têm ordenamento para seus elementos), e (b) se um elemento
aparece mais de uma vez, ele é tratado como se aparecesse apenas uma vez
(pois conjuntos não contêm elementos duplicados). Fim da nota paralela.
Continuando, uma chave primária é uma chave candidata que foi selecionada para
tratamento especial de alguma forma. Se a relação em questão tem apenas uma cha-
ve candidata, não faz nenhuma diferença real se decidirmos chamar essa chave de
“primária”. No entanto, se essa relação tem duas ou mais chaves candidatas, então é
habitual escolher uma delas como primária, significando que ela é, de alguma for-
ma, “mais igual do que as outras”. Vamos supor, por exemplo, que todo funcionário
5 N.T.: Construto é um elemento não tangível, criado para realizar uma determinada função (a rigor,
tudo em programação são construtos, já que nenhum deles existe fisicamente).
31Capítulo 1 ■ Preparando o cenário
sempre tenha tanto uma chave exclusiva de funcionário quanto um nome exclusivo
de funcionário – esse talvez não seja um exemplo muito realista, mas é bom osufi-
ciente para os propósitos atuais – de modo que {ENO} e {ENAME} sejam ambas
chaves candidatas para EMP. Então poderíamos escolher {ENO}, por exemplo, para
ser a chave primária.
Observe que eu disse que é habitual escolher uma chave primária. De fato, é habitual
– mas não é 100% necessário. Se houver apenas uma chave candidata, então haverá
pouca escolha e nenhum problema; mas se houver duas ou mais, então ter de esco-
lher uma e torná-la primária pode soar um tanto quanto arbitrário (pelo menos para
mim). Certamente, há situações em que não parece haver nenhum bom motivo para
fazermos tal escolha. Neste livro, portanto, vou geralmente seguir a disciplina da chave
primária – e, em figuras como a figura 1.1, vou indicar atributos de chave primária com
um sublinhado duplo6 –, mas desejo reforçar o fato de que são realmente as chaves
candidatas, e não as chaves primárias, que são significativas a partir de um ponto
de vista relacional. Parcialmente por esse motivo, deste ponto em diante vou utilizar
o termo chave, sem qualificação, para significar qualquer chave candidata, indepen-
dentemente de a chave candidata em questão ter sido designada como “primária”.
(Caso você esteja se perguntado, o “tratamento especial” dado às chaves primárias
com relação às chaves candidatas é, de qualquer modo, principalmente sintático em
natureza; ele não é fundamental e não é muito importante.)
Por fim, uma chave estrangeira (foreign key) é uma combinação, ou conjunto, de atri-
butos FK em alguma relação r2 de modo que cada valor de FK tenha de ser igual a
algum valor de alguma chave K em alguma relação r1 (r1 e r2 não são necessariamente
distintas)7. Com referência à figura 1.1, por exemplo, {DNO} é uma chave estrangeira
em EMP cujos valores devem corresponder a valores da chave {DNO} em DEPT
(como tentei sugerir por meio de uma seta identificada adequadamente na figura).
Aqui, por devem corresponder eu quero dizer que se, por exemplo, EMP contiver uma
tupla na qual o atributo DNO tenha o valor D2, então DEPT também deve conter uma
tupla na qual o atributo DNO tenha o valor D2 – pois, do contrário, EMP mostraria
algum funcionário como se estivesse em um departamento inexistente, e o banco de
dados não seria um “modelo fiel da realidade”.
Características de integridade
Uma restrição de integridade (restrição, para abreviar) é, basicamente, apenas uma
expressão booleana que deve ser avaliada como TRUE. No caso de departamentos
e funcionários, por exemplo, podemos ter uma restrição de forma que valores de
6 Veja o exercício 5.27 no capítulo 5 para obter mais explicações sobre essa convenção.
7 Essa definição é deliberadamente um tanto quanto simplificada. Uma definição melhor pode ser
encontrada no capítulo 5.
SQL e Teoria Relacional32
SALARY (salário) devam ser maiores do que zero. Agora, qualquer banco de dados
estará sujeito a inúmeras restrições; no entanto, todas essas restrições serão necessa-
riamente específicas ao banco de dados e serão, portanto, expressas em termos das
relações desse banco de dados. Por contraste, o modelo relacional como originalmente
formulado inclui duas restrições genéricas – genéricas, no sentido de que se aplicam a
qualquer banco de dados, livremente falando. Uma tem relação com chaves primárias
e outra, com chaves estrangeiras. Aqui estão elas:
• A regra de integridade de entidade: atributos de chave primária não permitem
nulos.
• A regra de integridade referencial: não deve haver nenhum valor de chave estran-
geira não correspondido.
Vou explicar a segunda regra, primeiro. Por valor de chave estrangeira não correspondido
quero dizer um valor de chave estrangeira para o qual não exista um valor igual ao da
chave candidata pertinente (a “chave-alvo”); assim, por exemplo, o banco de dados de
departamentos para funcionários estaria em violação da regra de integridade referen-
cial se incluísse, digamos, uma tupla EMP com um valor DNO de D2, mas nenhuma
tupla DEPT com esse mesmo valor DNO. Assim, a regra de integridade referencial
simplesmente explicita a semântica das chaves estrangeiras; o nome “integridade
referencial” deriva do fato de que um valor de chave estrangeira pode ser considerado
uma referência à tupla com esse mesmo valor para a chave-alvo correspondente. Na
prática, portanto, a regra simplesmente diz: se B referencia A, então A deve existir.
Quanto à regra de integridade de entidade, bem, aqui tenho um problema. O fato
é que rejeito o conceito de “nulos” inteiramente; ou seja, tenho a forte opinião de
que nulos não têm lugar no modelo relacional. (Codd, obviamente, pensava diferente,
mas tenho razões significativas para assumir essa posição.) Para explicar a regra de
integridade de entidade, portanto, preciso, nesse caso, suspender minha descrença
(pelo menos por alguns momentos). O que começarei a fazer agora... Mas, por favor,
entenda que voltarei a toda essa questão dos nulos nos capítulos 3 e 4.
Em essência, então, um nulo é um “marcador” que significa valor desconhecido. Cru-
cialmente, ele não é, em si, um valor; ele é, para repetir, um marcador, ou sinalizador.
Por exemplo, vamos supor que não conheçamos o salário do funcionário E2. Então,
em vez de inserir algum valor de SALARY real na tupla para o empregado E2 em rela-
ção a EMP – não podemos inserir um valor real, por definição, precisamente porque
não sabemos qual deve ser esse valor – marcamos a posição do SALARY dentro dessa
tupla como um nulo, como indicado aqui:
33Capítulo 1 ■ Preparando o cenário
Agora, é importante entender que essa tupla não contém nada na posição SALARY.
Porém é muito difícil fazer uma imagem do nada! Tentei mostrar que a posição SALARY
está vazia, na figura anterior, usando um sombreado, mas seria mais correto não mostrar
nada nessa posição. Seja como for, utilizarei essa mesma convenção de representação
de posições vazias com sombreado em outros locais deste livro – mas esse sombreado,
repito, não representa nenhum tipo de valor. Você pode pensar nisso (o sombreado,
quer dizer) como constituindo o “marcador” – ou sinalizador de nulo, se preferir.
Retornando à regra de integridade de entidade: em termos da relação EMP, então,
essa regra diz, de maneira solta, que a tupla de determinado funcionário pode ter um
nome desconhecido, ou um número de departamento desconhecido, ou um salário
desconhecido – mas ela não pode ter um número de funcionário desconhecido. A jus-
tificativa para essa situação é que, se o número de funcionário fosse desconhecido, nem
sequer saberíamos de qual “entidade” (isto é, qual funcionário) estaríamos falando.
Isso é tudo que desejo dizer sobre nulos por enquanto. Por favor, esqueça-se deles
até segunda ordem.
Características manipulativas
A parte manipulativa do modelo, por sua vez, se divide em duas:
• A álgebra relacional, que é uma coleção de operadores (por exemplo, de diferença,
ou MINUS) que podem ser aplicados à relação.
• Um operador de atribuição relacional, que permite que o valor de alguma ex-
pressão relacional (por exemplo, r1 MINUS r2, onde r1 e r2 são relações) seja
atribuído a alguma relação.
O operador de atribuição relacional é, fundamentalmente, a forma como atualizações
são feitas no modelo relacional; terei mais a dizer sobre ele futuramente, na seção
“Relações versus Relvars”. Nota: sigo a convenção habitual ao longo deste livro ao uti-
lizar o termo genérico atualização para me referir aos operadores INSERT, DELETE e
UPDATE (e de atribuição) considerados coletivamente. Quando quiser me referir ao
operador UPDATE especificamente, vou utilizá-lo todo em letras maiúsculas, como
acabamos de ver.
Quanto à álgebra relacional, ela consiste em um conjunto de operadores que – falando
bastante livremente – permitem-nos derivar “novas” relações de relações “antigas”.
Cada operador desse tipo toma uma ou mais relações como entrada e produz outra
relação como saída; por exemplo, a diferença (MINUS) toma duas relações como
entrada e “subtrai” umada outra, para derivar outra relação como saída. E é muito
importante que a saída seja outra relação: essa é a bem conhecida propriedade de
fechamento da álgebra relacional. A propriedade de fechamento é o que nos permite
SQL e Teoria Relacional34
escrever expressões relacionais aninhadas; já que a saída de cada operação é do
mesmo tipo da entrada, a saída de uma operação pode se tornar a entrada de outra.
Por exemplo, podemos tomar a diferença r1 MINUS r2, alimentar o resultado como
entrada de uma união com alguma relação r3, alimentar esse resultado para uma
intersecção com alguma relação r4, e assim por diante.
Agora, um número qualquer de operadores pode ser definido que se encaixe na
simples definição de que “uma ou mais relações entram, exatamente uma relação
sai”. Aqui, descrevo brevemente quais costumam ser imaginados como os operadores
originais (essencialmente, aqueles que Codd definiu em seus textos iniciais)8; darei
mais detalhes no capítulo 6 e, no capítulo 7, também descreverei vários operadores
adicionais. A figura 1.2 é uma representação pictórica desses operadores originais.
Figura 1.2 – Álgebra relacional original.
Nota: se você não está familiarizado com esses operadores e considera as descrições
um pouco difíceis de acompanhar, não se preocupe com isso; como já disse, vou falar
sobre isso muito mais detalhadamente, com vários exemplos, em capítulo futuros.
8 Exceto que Codd definiu também um operador chamado de divisão. Vou explicar no capítulo 7
porque omito esse operador aqui.
35Capítulo 1 ■ Preparando o cenário
Restrição
Retorna uma relação contendo todas as tuplas de uma relação específica que
satisfaçam a uma condição especificada. Por exemplo, podemos restringir a
relação EMP a apenas aquelas tuplas cujo valor DNO seja D2.
Projeção
Retorna uma relação contendo todas as (sub)tuplas que permaneçam em uma
relação especificada depois que atributos especificados foram removidos. Por
exemplo, podemos projetar a relação EMP em apenas os atributos ENO e
SALARY (removendo, dessa forma, os atributos ENAME e DNO).
Produto
Retorna uma relação contendo todas as possíveis tuplas que sejam uma com-
binação de duas tuplas, uma de cada duas relações especificadas. Nota: esse
operador também é conhecido variavelmente como produto cartesiano (às vezes,
produto cartesiano estendido ou expandido), produto cruzado, junção cruzada e
junção cartesiana; aliás, ele é apenas um caso especial de junção, como veremos
no capítulo 6.
Intersecção
Retorna uma relação contendo todas as tuplas que apareçam em ambas as rela-
ções especificadas. (Na realidade, a intersecção, tal como o produto, é também
um caso especial de junção, como veremos no capítulo 6.)
União
Retorna uma relação contendo todas as tuplas que apareçam em qualquer uma
das duas, ou em ambas as relações especificadas.
Diferença
Retorna uma relação contendo todas as tuplas que apareçam na primeira, mas
não na segunda das duas relações especificadas.
Junção
Retorna uma relação contendo todas as tuplas possíveis que sejam uma com-
binação de duas tuplas, uma de cada duas relações especificadas, de modo que
as duas tuplas que contribuam para qualquer tupla de resultado tenham um
valor comum para os atributos comuns das duas relações (e esse valor comum
aparece apenas uma vez, e não duas, nessa tupla de resultado). Nota: esse tipo
de junção era originalmente chamado de junção natural, para distingui-lo dos
vários outros tipos que serão discutidos futuramente neste livro. Como, no
SQL e Teoria Relacional36
entanto, uma junção natural está longe de ser o tipo mais importante, tornou-
-se prática padrão tomar-se o termo não qualificado junção como significando
a junção natural especificamente; seguirei essa prática neste livro.
Um último ponto antes de fecharmos esta subseção: como você provavelmente sabe,
existe também algo chamado cálculo relacional. O cálculo relacional pode ser con-
siderado uma alternativa à álgebra relacional; ou seja, em vez de dizer que a parte
manipulativa do modelo relacional consiste na álgebra relacional (mais a atribuição
relacional), podemos igualmente dizer que ela consiste no cálculo relacional (mais
a atribuição relacional). Os dois são equivalentes e intercambiáveis, no sentido de
que para cada expressão algébrica existe uma expressão logicamente equivalente
no cálculo e vice-versa. Falarei mais sobre cálculo futuramente, principalmente nos
capítulos 10 e 11.
O exemplo corrente
Finalizarei esta breve revisão apresentando o exemplo que vou usar como base para a
maioria das discussões, se não todas, do restante do livro: o familiar – para não dizer
banalizado – banco de dados de fornecedores e peças. (Peço desculpas por mais uma
vez trazer à vista esse velho cavalo de batalha, mas acredito que o uso de um mesmo
exemplo em uma variedade de livros e outras publicações possa ajudar, e não preju-
dicar, o aprendizado.) Valores de exemplo são mostrados na figura 1.3. Para elaborar:
Figura 1.3 – Banco de dados de fornecedores e peças – valores de exemplo.
Fornecedores (suppliers)
A relação S denota fornecedores (mais precisamente, fornecedores por contrato).
Cada fornecedor tem um número de fornecedor (SNO), exclusivo para esse
fornecedor (como você pode ver pela figura, tornei {SNO} a chave primária);
um nome (SNAME), não necessariamente exclusivo (ainda que os valores de
37Capítulo 1 ■ Preparando o cenário
SNAME na figura 1.3 parecem ser exclusivos); um valor de estado (STATUS),
representando algum tipo de nível de classificação ou de preferência entre
fornecedores disponíveis; e uma localização (CITY).
Peças (parts)
A relação P denota peças (mais precisamente, tipos de peças). Cada tipo de peça
tem um número de peça (PNO) que é exclusivo ({PNO} é a chave primária);
um nome (PNAME); uma cor (COLOR); um peso (WEIGHT); e uma locali-
zação onde as peças desse tipo estão armazenadas (CITY).
Entregas (shipments)
A relação SP denota entregas (ela mostra quais peças são fornecidas, ou entre-
gues, e por quais fornecedores). Cada entrega tem um número de fornecedor
(SNO), um número de peça (PNO) e uma quantidade (QTY). Para efeito do
exemplo, presumo que haja, em um momento qualquer, no máximo uma entre-
ga para um determinado fornecedor, e uma determinada peça ({SNO,PNO} é
a chave primária; além disso, {SNO} e {PNO} são ambas chaves estrangeiras,
correspondendo às chaves primárias de S e P, respectivamente). Note que o
banco de dados da figura 1.3 inclui um fornecedor, o fornecedor S5, que não
tem nenhuma entrega.
Modelo versus implementação
Antes de avançarmos, há um ponto importante que preciso explicar, pois sustenta
todo o restante a ser discutido neste livro. O modelo relacional é, evidentemente, um
modelo de dados. Infelizmente, no entanto, esse último termo tem dois significados
bastante distintos no mundo dos bancos de dados. O primeiro e mais fundamental
é este:
Definição: um modelo de dados (primeiro sentido) é uma definição abstrata,
autocontida e lógica das estruturas de dados, dos operadores de dados, e assim
por diante; reunidos, esses fatores formam a máquina abstrata com a qual os
usuários interagem.
Esse é o significado em que pensamos quando falamos sobre o modelo relacional em
particular. E, armados dessa definição, podemos, de modo proveitoso e importante,
avançar para distinguir um modelo de dados, nesse primeiro sentido, de sua imple-
mentação, que pode ser definida desta forma:
Definição: uma implementação de determinado modelo de dados é uma reali-
zação física em uma máquina real dos componentes da máquina abstrata que,
reunidos, constituem esse modelo.
SQL e Teoria Relacional38
Deixe-me ilustrar essas definições em termos do modelo relacional, especificamente.
Em primeiro lugar, considere o conceito de relação em si. Esse conceito é parte do
modelo: usuários têm de saber quais são as relações, têm de saber que elas são for-
madas por tuplas e atributos, têm de saber como interpretá-las,e assim por diante.
Tudo isso é parte do modelo. Porém eles não têm de saber como as relações são fisi-
camente armazenadas no disco, como valores de dados individuais são fisicamente
codificados ou que índices e outros caminhos de acesso existem; tudo isso é parte
da implementação, e não parte do modelo.
Ou considere o conceito de uma junção: usuários têm de saber o que é uma junção,
têm de saber como invocar uma junção, têm de saber qual a apresentação do resul-
tado de uma junção, e assim por diante. Novamente, tudo isso é parte do modelo.
No entanto eles não têm de saber como as junções são fisicamente implementadas,
quais transformações de expressão ocorrem nos bastidores, quais índices ou outros
caminhos de acesso são utilizados ou que operações físicas de E/S ocorrem; tudo
isso é parte da implementação, e não parte do modelo.
E mais um exemplo: chaves candidatas (chaves, para abreviar) são, uma vez mais, parte
do modelo, e usuários definitivamente têm de saber o que as chaves são; em parti-
cular, eles têm de saber que tais chaves têm a propriedade de exclusividade. Agora, a
exclusividade das chaves é reforçada nos sistemas atuais por meio do que é chamado
de um “índice exclusivo”; mas índices em geral, e índices exclusivos em particular, não
são parte do modelo, eles são parte da implementação. Assim, um índice exclusivo
não deve ser confundido com uma chave no sentido relacional, ainda que o primeiro
possa ser utilizado para implementar o segundo (mais precisamente, para implementar
alguma restrição de chave – veja o capítulo 8).
Em resumo, então:
• O modelo (primeiro significado) é o que o usuário precisa saber.
• A implementação é o que o usuário não precisa saber.
Por favor, compreenda que não estou dizendo aqui que usuários estão proibidos de
conhecer a implementação; estou apenas dizendo que eles não têm de fazê-lo. Em
outras palavras, tudo que está relacionado à implementação deve estar, pelo menos
potencialmente, escondido do usuário.
Aqui estão algumas consequências importantes das definições anteriores. Em primeiro
lugar, observe que tudo que está relacionado ao desempenho é fundamentalmente
uma questão de implementação, e não de modelo. Esse ponto é amplamente mal
compreendido! Por exemplo, muitas vezes ouvimos afirmações no sentido de que
“junções são lentas”. Porém tais afirmações simplesmente não fazem sentido. Uma
junção é parte do modelo, e o modelo como tal não pode ser dito como sendo rápido
39Capítulo 1 ■ Preparando o cenário
ou lento; apenas a implementação pode ser dita como detentora de qualquer quali-
dade desse tipo. Assim, podemos razoavelmente dizer que algum produto específico
X tenha uma implementação mais rápida ou mais lenta de alguma junção específica,
em alguns dados específicos, do que algum outro produto específico Y – mas isso é
praticamente tudo.
Agora, não quero passar uma impressão errada aqui. É verdade que o desempenho
é fundamentalmente uma questão de implementação; no entanto, isso não significa
que uma boa implementação terá um bom desempenho se você utilizar o modelo
erroneamente. Na realidade, essa é precisamente uma das razões por que você precisa
conhecer o modelo: para que você não o utilize erroneamente. Se você escrever uma
expressão como S JOIN SP, está dentro de seus direitos esperar que o sistema a im-
plemente com eficiência; mas se você insistir, com efeito, em codificar manualmente
a junção, talvez desta forma (em pseudocódigo) –
do for all tuples in S ;
fetch S tuple into TS , TN , TT , TC ;
do for all tuples in SP with SNO = TS ;
fetch SP tuple into TS , TP , TQ ;
emit TS , TN , TT , TC , TP , TQ ;
end ;
end ;
–, então não haverá como você obter um bom desempenho. Recomendação: não faça
isso. Sistemas relacionais não devem ser utilizados como simples métodos de acesso.9
Por falar nisso, essas observações sobre desempenho também se aplicam à SQL. Assim
como os operadores relacionais (de junção e outros), não se pode dizer que a SQL
seja rápida ou lenta – apenas implementações podem razoavelmente ser descritas
em tais termos –, mas também é possível usar SQL de forma a garantir um mau
desempenho. Ainda que, em geral, eu tenha pouco a dizer sobre desempenho neste
livro, vou ocasionalmente apontar certas implicações de desempenho naquilo que
estou recomendando.
Nota paralela: gostaria de me aprofundar por um momento na questão de de-
sempenho. Em geral, minhas recomendações neste livro nunca têm por base
o desempenho como um motivador principal; afinal, sempre foi um objetivo
do modelo relacional retirar considerações de desempenho das mãos do usu-
ário e colocá-las, em vez disso, nas mãos do sistema. Entretanto, não é preciso
dizer que esse objetivo não foi totalmente atingido, e assim (como eu já disse)
9 Mais de um revisor observou que essa frase não fazia sentido (como um sistema pode ser utilizado
como um método?). Bem, se você é jovem demais para estar familiarizado com o termo método
de acesso, eu o invejo; mas a realidade é que, esse termo, ainda que inapropriado fosse (e seja), foi
amplamente usado durante muitos anos como significando um simples recurso de E/S de nível
de registro, de um tipo ou de outro.
SQL e Teoria Relacional40
a meta de utilizar SQL relacionalmente deve, às vezes, ser comprometida no
interesse de se obter um desempenho satisfatório. Essa é outra razão por que,
como disse antes neste capítulo, a regra suprema deve ser: “você pode fazer o
que quiser, desde que saiba o que está fazendo”. Fim da nota paralela.
De volta ao modelo versus implementação, e aos pontos que surgem dessa distinção, o
segundo ponto é que, como você provavelmente percebeu, é precisamente a separação
de modelo e implementação que nos permite obter independência de dados físicos. A
independência de dados físicos – não é um ótimo termo, mas parece que estamos
presos a ele – significa que temos a liberdade de fazer mudanças na forma como os
dados são fisicamente armazenados e acessados sem termos de fazer as mudanças
correspondentes na forma como os dados são percebidos pelo usuário. Agora, a razão
por que podemos querer alterar esses detalhes de armazenamento e acesso é, tipica-
mente, desempenho; e o fato de podermos fazer tais alterações sem ter de modificar
a forma como os dados aparecem para o usuário significa que programas e consultas
existentes, e outros elementos do tipo, podem todos ainda funcionar depois da alte-
ração. De forma muito importante, então, a independência de dados físicos significa
proteger o investimento em treinamento de usuário e aplicações (investimento também no
projeto de bancos de dados lógicos, devo acrescentar).
É uma consequência de tudo que acabamos de ver que, como indicado previamente,
índices e, na realidade, caminhos de acesso físico de qualquer tipo sejam adequa-
damente parte da implementação, e não do modelo; eles pertencem aos bastidores
e devem estar escondidos do usuário. (Note que caminhos de acesso como tais não
são mencionados em nenhum lugar do modelo relacional.) Pelos mesmos motivos,
eles também devem ser rigorosamente excluídos da SQL. Recomendação: evite o
uso de qualquer construto SQL que viole esse preceito. (Na realidade, não há nada
no padrão que o faça, até onde estou ciente, mas sei que o mesmo não é verdadeiro
quanto a certos produtos SQL.)
De qualquer forma, como você pode ver a partir das definições anteriores, a distinção
entre modelo e implementação é, na realidade, apenas um caso especial – um caso
especial muito importante – da distinção habitual entre considerações lógicas e físicas
em geral. Infelizmente, entretanto, a maioria dos sistemas SQL atuais não faz essas
distinções tão claramente como deveria. Como consequência direta, entregam muito
menos independência de dados físicos do que deveriam, e muito menos do que, em
princípio, sistemas relacionais são capazes. Voltarei a essa questão na próxima seç��o.
Agora, volto-me para o segundo significadodo termo modelo de dados, com o qual,
ouso dizer, você deve estar bastante familiarizado. Ele pode ser definido desta forma:
Definição: um modelo de dados (segundo sentido) é um modelo dos dados –
especialmente dos dados persistentes – de alguma empresa específica.
41Capítulo 1 ■ Preparando o cenário
Em outras palavras, um modelo de dados no segundo sentido é apenas um projeto
de banco de dados (lógico e, possivelmente, um tanto quanto abstrato). Por exem-
plo, podemos falar do modelo de dados de algum banco, algum hospital ou algum
departamento do governo.
Tendo explicado esses dois significados distintos, gostaria de chamar sua atenção para
uma analogia que acredito que esclareça o relacionamento entre eles:
• Um modelo de dados no primeiro sentido é como uma linguagem de progra-
mação, cujos construtos podem ser usados para solucionar muitos problemas
específicos, mas que, por si só, não têm conexão direta com nenhum desses
problemas específicos.
• Um modelo de dados no segundo sentido é como um programa específico
escrito nessa linguagem – ele utiliza os recursos fornecidos pelo modelo, no
primeiro sentido do termo, para solucionar algum problema específico.
Por falar nisso, é uma consequência do que vimos que, se estamos falando sobre mo-
delos de dados no segundo sentido, então podemos razoavelmente falar de “modelos
relacionais” no plural, ou de “um” modelo relacional (com um artigo indefinido).
Porém, se estamos falando sobre modelos de dados no primeiro sentido, então há
apenas um modelo relacional, e ele é o modelo relacional (com o artigo definido). Terei
mais a dizer sobre esse último ponto no apêndice A.
Pelo restante deste livro, vou utilizar o termo modelo de dados, ou, de forma geral,
apenas modelo, para simplificar, exclusivamente no primeiro sentido.
Propriedades de relações
Agora vamos retornar para nossa análise de conceitos relacionais básicos. Nesta seção,
quero me concentrar em algumas propriedades das relações em si. Em primeiro lugar,
toda relação tem um cabeçalho e um corpo: o cabeçalho é um conjunto de atributos
(onde, pelo termo atributo, quero dizer, muito especificamente, um par nome-de-atribu-
to/nome-de-tipo, sendo que não há dois atributos com o mesmo nome de atributo), e o
corpo é um conjunto de tuplas que se conformam a esse cabeçalho. No caso da relação
de fornecedores (S) da figura 1.3, por exemplo, há quatro atributos no cabeçalho e cinco
tuplas no corpo. Note, portanto, que na realidade uma relação não contém tuplas – ela
contém um corpo, e esse corpo, por sua vez, contém as tuplas –, mas falamos geralmente
como se as relações contivessem tuplas diretamente, por simplicidade.
Por falar nisso, ainda que esteja estritamente correto dizer que o cabeçalho consiste
em pares nome-de-atributo/nome-de-tipo, é habitual omitir os nomes de tipo em
figuras como a figura 1.3, e, dessa forma, agir como se o cabeçalho fosse apenas um
conjunto de nomes de atributos. Por exemplo, o atributo STATUS tem, de fato, um
SQL e Teoria Relacional42
tipo – INTEGER, digamos –, mas eu não o mostrei na figura 1.3. Entretanto, você
nunca deve esquecer que ele está lá!
Em seguida, o número de atributos no cabeçalho é o grau (às vezes, a aridade), e o
número de tuplas no corpo é a cardinalidade. Por exemplo, a relação S na figura 1.3
tem grau 4 e cardinalidade 5; da mesma forma, a relação P dessa figura tem grau 5
e cardinalidade 6, e a relação SP dessa figura tem grau 3 e cardinalidade 12. Nota: o
termo grau também é usado em conexão com as tuplas10. Por exemplo, as tuplas na
relação S são (assim como a relação S em si) todas de grau 4.
Além disso, relações nunca contêm tuplas duplicadas. Essa propriedade se verifica
porque um corpo é definido como um conjunto de tuplas, e conjuntos em matemática
não contêm elementos duplicados. Agora, a SQL falha aqui, como estou certo de que
você sabe: é permitido que tabelas SQL contenham linhas duplicadas, não sendo,
portanto, relações em geral. Por favor, compreenda, portanto, que ao longo deste
livro vou sempre usar o termo “relação” para representar uma relação – sem tuplas
duplicadas, por definição – e não uma tabela SQL. Compreenda também, por favor,
que operações relacionais sempre produzem um resultado sem tuplas duplicadas,
novamente por definição. Por exemplo, projetar a relação de fornecedores da figura 1.3
sobre CITY produz o resultado mostrado aqui na esquerda, e não aquele da direita:
(O resultado da esquerda pode ser obtido por meio da consulta SQL SELECT
DISTINCT CITY FROM S. Omitindo esse DISTINCT, conseguimos o resultado não
relacional da direita. Note, em particular, que a tabela da direita não tem nenhum
sublinhado duplo; isso porque ela não tem nenhuma chave e, portanto, nenhuma
chave primária a fortiori.)
Além disso, as tuplas de uma relação são não ordenadas, de cima para baixo. Essa pro-
priedade se verifica porque, novamente, um corpo é definido como sendo um conjunto,
e conjuntos em matemática não têm ordenamento em seus elementos (portanto, por
exemplo, {a,b,c} e {c,a,b} são o mesmo conjunto em matemática, e uma afirmação
semelhante naturalmente se aplica ao modelo relacional). Evidentemente, quando
desenhamos uma relação como uma tabela no papel, temos realmente de mostrar as
linhas em alguma ordem de cima para baixo, mas essa ordenação não corresponde
a nada relacional. No caso da relação de fornecedores como representada na figura
1.3, por exemplo, eu poderia ter mostrado as linhas em qualquer ordem – digamos
10 Ele também é utilizado em conexão com chaves (veja o capítulo 5).
43Capítulo 1 ■ Preparando o cenário
fornecedor S3, depois S1, depois S5, depois S4, depois S2 –, e a figura ainda repre-
sentaria a mesma relação. Nota: o fato de as relações não terem ordenação para suas
tuplas não significa que consultas não possam incluir uma especificação ORDER BY,
mas significa, na realidade, que tais consultas produzem um resultado que não é uma
relação. ORDER BY é útil para apresentação de resultados, mas não é um operador
relacional como tal.
De modo semelhante, os atributos de uma relação também são não ordenados da
esquerda para a direita, pois um cabeçalho também é um conjunto matemático.
Novamente, quando desenhamos uma relação como uma tabela no papel, temos de
apresentar as colunas em alguma ordem da esquerda para a direita, mas essa orde-
nação não corresponde a nada relacional. No caso da relação de fornecedores como
representada na figura 1.3, por exemplo, eu poderia ter mostrado as colunas em qual-
quer ordem da esquerda para a direita – digamos STATUS, SNAME, CITY, SNO –, e a
figura ainda representaria a mesma relação no modelo relacional. Incidentalmente, a
SQL também falha aqui. Tabelas SQL têm uma ordenação da esquerda para a direita
para suas colunas (outro motivo pelo qual tabelas SQL não são relações em geral). Por
exemplo, estas duas figuras representam a mesma relação, mas tabelas SQL diferentes:
(As consultas SQL correspondentes são SELECT SNO, CITY FROM S e SELECT CITY,
SNO FROM S, respectivamente. Agora, você pode estar pensando que as diferenças
entre essas duas consultas, e entre essas duas tabelas, dificilmente sejam muito sig-
nificativas; na realidade, entretanto, elas têm algumas consequências sérias, algumas
das quais veremos em capítulos futuros. Veja, por exemplo, a discussão do operador
JOIN explícito da SQL no capítulo 6.)
Por fim, relações são sempre normalizadas (de forma equivalente, elas estão na primeira
forma normal, 1NF)11. Informalmente, o que isso significa é que, em termos da figura
tabular de uma relação, em toda intersecção de linha e coluna sempre vemos apenas
um único valor. Mais formalmente, isso significa que toda tupla em toda relação
contém apenas um único valor, do tipo apropriado, em cada posição de atributo.
Nota: terei muito mais a dizer sobre essa questão particular no próximo capítulo.
Antes de encerrar esta seção, gostaria de enfatizar algo que já mencionei váriasvezes:
mais especificamente, o fato de que há uma diferença lógica entre uma relação como
11 “Primeira” forma normal porque, como estou certo de que você sabe, é possível definir uma série
de formas normais “mais elevadas” – segunda forma normal, terceira forma normal e assim por
diante – que são relevantes à disciplina do projeto de bancos de dados.
SQL e Teoria Relacional44
tal por um lado, e uma imagem de uma relação, como mostrada, por exemplo, nas
figuras 1.1 e 1.3, por outro. Para dizer mais uma vez, os construtos nas figuras 1.1 e 1.3
não são relações, mas, em vez disso, imagens de relações – às quais geralmente me
refiro como tabelas, apesar do fato de tabela ser uma palavra carregada em contextos
SQL. Evidentemente, relações e tabelas realmente têm certos pontos de semelhança,
e, em contextos informais, é habitual, e geralmente aceitável, dizermos que elas re-
presentam o mesmo conceito. Porém quando estamos tentando ser precisos – e agora
estou tentando ser um pouco preciso – temos realmente de reconhecer que os dois
conceitos não são idênticos.
Como uma nota paralela, observo que, mais genericamente, há uma diferença lógica
entre um elemento de qualquer tipo e uma imagem desse elemento. Há uma famosa
pintura de Magritte que ilustra belamente o ponto que estou tentando defender aqui. A
pintura é a de um cachimbo de tabaco normal, mas na parte inferior Magritte escreveu
Ceçi n’est pas une pipe (Isto não é um cachimbo)... O sentido, é claro, é de que obvia-
mente a pintura não é um cachimbo – em vez disso, ela é a pintura de um cachimbo.
Tendo dito tudo isso, devo agora dizer também que é, na realidade, uma grande
vantagem do modelo relacional que seu objeto abstrato básico, a relação, tenha uma
representação tão simples no papel; é essa representação simples no papel que faz com
que os sistemas relacionais sejam fáceis de ser usados e fáceis de ser compreendidos,
e também facilita o raciocínio sobre a forma como tais sistemas se comportam. No
entanto, também é, infelizmente, provável que essa representação simples realmente
sugira alguns pontos que não sejam verdadeiros (por exemplo, que haja uma orde-
nação de tuplas de cima para baixo).
E mais um ponto adicional: como já disse, há uma diferença lógica entre uma relação
e uma imagem de uma relação. O conceito da diferença lógica deriva de uma máxima
de Wittgenstein:
Todas as diferenças lógicas são grandes diferenças.
Essa noção é extraordinariamente útil; como uma “ferramenta da mente”, ela é de
grande auxílio para um raciocínio claro e preciso, e pode ser muito útil na identifica-
ção e análise de algumas confusões que são, infelizmente, muito comuns no mundo
dos bancos de dados. Vou recorrer a ela muitas vezes nas páginas seguintes. Nesse
meio-tempo, deixe-me destacar que já encontramos algumas diferenças lógicas im-
portantes. Aqui estão algumas delas:
• SQL versus o modelo relacional.
• Modelo versus implementação.
• Modelo de dados (primeiro sentido) versus modelo de dados (segundo sentido).
E encontraremos muitas outras nas páginas que virão.
45Capítulo 1 ■ Preparando o cenário
Alguns pontos cruciais
Neste momento, gostaria de mencionar alguns pontos cruciais que vou elaborar em
capítulos futuros (especialmente no capítulo 3). Os pontos em questão são estes:
• Todo subconjunto de uma tupla é uma tupla: por exemplo, considere a tupla do
fornecedor S1 na figura 1.3. Essa tupla tem quatro componentes que corres-
pondem aos quatro atributos SNO, SNAME, STATUS e CITY. Se removermos
(digamos) o componente SNAME, o que sobra ainda é realmente uma tupla:
a saber, uma tupla com três componentes (uma tupla de grau 3).
• Todo subconjunto de um cabeçalho é um cabeçalho: por exemplo, considere o
cabeçalho da relação de fornecedores na figura 1.3. Esse cabeçalho tem quatro
atributos: SNO, SNAME, STATUS e CITY. Se removermos (digamos) os atri-
butos SNAME e STATUS, o que sobra ainda é um cabeçalho, um cabeçalho
de grau 2.
• Todo subconjunto de um corpo é um corpo: por exemplo, considere o corpo da
relação de fornecedores da figura 1.3. Esse corpo tem cinco tuplas, correspon-
dendo aos cinco fornecedores S1, S2, S3, S4 e S5. Se removermos (digamos) as
tuplas S1 e S3, o que sobra ainda é um corpo, um corpo de cardinalidade três.
Nota: talvez eu deva afirmar apenas para registro que, ao longo deste livro – de acor-
do com a prática normal – tomarei expressões na forma “B é um subconjunto de A”
como incluindo a possibilidade de que A e B possam ser iguais. Assim, por exemplo,
toda tupla é um subconjunto dela mesma (e assim também todo cabeçalho, e assim
também todo corpo). Quando quiser excluir tal possibilidade, falarei explicitamente
em termos de subconjuntos próprios. Por exemplo, nossa tupla habitual do fornecedor
S1 é certamente um subconjunto de si mesma, mas não é um subconjunto próprio
de si mesma. Além disso, as afirmações anteriores aplicam-se igualmente aos super-
conjuntos, mutatis mutandis (mudando o que tem que ser mudado); por exemplo, a
tupla do fornecedor S1 é um superconjunto de si mesma, mas não um superconjunto
próprio de si mesma.12
Também gostaria de dizer algo sobre a noção crucial de igualdade – especialmente pelo
fato de essa noção ser aplicada a tuplas e a relações, especificamente. Em geral, dois
valores são iguais se – e apenas se – eles tiverem o mesmo valor. Por exemplo, o inteiro
3 é igual ao inteiro 3, e a nada mais – em particular, ele não é igual a qualquer outro
inteiro. Exatamente da mesma forma, duas tuplas são iguais se – e apenas se – elas
12 O que descrevi nesse parágrafo é a convenção matemática padrão; no entanto, você pode ter
encontrado uma convenção diferente em contextos menos formais. Para ser específico, algumas
pessoas utilizam “B é um subconjunto de A” como significando o que quero dizer quando digo
que B é um subconjunto próprio de A, e utilizam “B é um subconjunto de ou igual a A” como
significando o que quero dizer quando digo que B é um subconjunto de A. Da mesma forma para
superconjuntos, mutatis mutandis.
SQL e Teoria Relacional46
forem exatamente a mesma tupla. Com referência à figura 1.3, por exemplo, a tupla
do fornecedor S1 é igual à tupla do fornecedor S1, e a nada mais – em particular, ela
não é igual a qualquer outra tupla. Em outras palavras, duas tuplas são iguais se – e
apenas se – (a) elas envolverem exatamente os mesmos atributos e os (b) valores de
atributo correspondentes forem iguais, por sua vez.
Ademais (isso pode parecer óbvio, mas precisa ser dito), duas tuplas são duplicatas
uma da outra se – e apenas se – elas forem iguais.
Voltando-nos agora para as relações: exatamente da mesma forma, duas relações são
iguais se – e apenas se – elas forem exatamente a mesma relação. Com referência à
figura 1.3, por exemplo, a relação de fornecedores é igual à relação de fornecedores
e a nada mais – em particular, ela não é igual a qualquer outra relação. Em outras
palavras, duas relações são iguais se – e apenas se – os seus cabeçalhos forem iguais
e seus corpos forem iguais.
Como já disse, vou retornar a essas questões no capítulo 3. Aqui, deixe-me apenas
acrescentar que a noção de igualdade de tuplas em particular é absolutamente fun-
damental – praticamente tudo no modelo relacional é crucialmente dependente dela,
como veremos.
Relações de base versus relações derivadas
Como expliquei antes, os operadores da álgebra relacional nos permitem iniciar com
algumas relações dadas, como aquelas representadas na figura 1.3, e obter relações
adicionais a partir das primeiras (por exemplo, efetuando consultas). As relações
dadas são referidas como relações de base, as outras são relações derivadas. Para
darmos nosso primeiro passo, portanto, um sistema relacional tem, em primeiro
lugar, de fornecer meios para definição dessas relações de base. Em SQL, essa tarefa
é realizada pela instrução CREATE TABLE (a contraparte SQL para uma relação de
base seria, é claro, uma tabela de base, queé o que CREATE TABLE cria). E relações
de base obviamente precisam ser nomeadas – por exemplo:
CREATE TABLE S ... ;
Mas certas relações derivadas, incluindo, em particular, as que são chamadas de visões
(views), também são nomeadas. Uma visão (também conhecida como uma relação virtual)
é uma relação nomeada cujo valor em um tempo qualquer t é o resultado da avaliação
de determinada expressão relacional nesse tempo t. Aqui está um exemplo SQL:
CREATE VIEW SST_PARIS AS
( SELECT SNO , STATUS
FROM S
WHERE CITY = 'Paris' ) ;
47Capítulo 1 ■ Preparando o cenário
Em princípio, você pode operar sobre visões exatamente como se elas fossem relações
de base13, mas elas não são relações de base. Em vez disso, você pode pensar em uma
visão como sendo “materializada” – na prática, você pode pensar em uma relação de
base sendo construída e cujo valor seja obtido avaliando-se a expressão relacional
especificada – no momento em que a visão em questão é referenciada. Porém devo
enfatizar que pensar em visões como sendo materializadas dessa forma quando elas
são referenciadas é puramente conceitual; isso é apenas uma forma de pensar; não é
o que deve acontecer; e não funcionaria para operações de atualização de qualquer
forma. A forma como as visões devem realmente funcionar é explicada no capítulo 9.
Por falar nisso, há um ponto importante que preciso defender aqui. Você muitas vezes
ouvirá a diferença entre relações de base e visões sendo descrita desta forma (cuidado!
aí vêm algumas inverdades!):
• Relações de base realmente existem – ou seja, elas são fisicamente armazenadas
no banco de dados.
• Visões, por contraste, não “existem realmente” – elas meramente fornecem
formas diferentes de analisarmos as operações de base.
No entanto o modelo relacional não tem nada a dizer quanto ao que é fisicamente
armazenado! – aliás, ele não tem nada a dizer sobre nenhuma questão de armaze-
namento físico. Em particular, ele categoricamente não diz que relações de base são
fisicamente armazenadas. O único requisito é que haja algum mapeamento entre o
que é fisicamente armazenado e essas relações de base, para que essas relações de base
possam de alguma forma ser obtidas quando forem necessárias (conceitualmente,
de qualquer modo). Se as relações de base puderem ser obtidas a partir do que quer
que esteja fisicamente armazenado, então tudo mais também poderá. Por exemplo,
poderíamos armazenar fisicamente a junção de fornecedores e entregas, em vez de
armazená-las separadamente; então, relações de base S e SP poderiam ser obtidas,
conceitualmente, tomando-se projeções apropriadas dessa junção. Em outras palavras:
relações de base não são mais (nem menos!) “físicas” do que visões, no que se refere
ao modelo relacional.
O fato de o modelo relacional não dizer nada sobre o armazenamento físico é deli-
berado, é claro. A ideia era fornecer a implementadores a liberdade de implementar o
modelo da forma que escolhessem – em particular, de qualquer forma que parecesse
produzir bom desempenho – sem comprometer a independência de dados físicos.
O fato triste, no entanto, é que a maioria dos fornecedores de produtos SQL não
parece ter entendido esse ponto (ou não se dispôs a enfrentar o desafio, de qualquer
13 Talvez você esteja pensando que essa afirmação não possa ser 100% verdadeira para operações de
atualização. Se for assim, você pode estar certo no que se refere aos produtos SQL de hoje; ainda
assim, continuo afirmando que isso é verdade em princípio. Veja a seção “Operações de atualização”
no capítulo 9 para discussões adicionais.
SQL e Teoria Relacional48
forma); em vez disso, eles mapeiam tabelas de base de modo razoavelmente direto ao
armazenamento físico14, e (como mencionado previamente) seus produtos, portanto,
oferecem muito menos independência de dados físicos do que sistemas relacionais
são ou deveriam ser capazes. De fato, essa situação é refletida no próprio padrão SQL
(assim como na maioria das outras documentações SQL), o qual tipicamente – quase
sempre, aliás – fala em termos de “tabelas e visões”. Claramente, qualquer pessoa
que fale dessa forma está com a impressão de que tabelas e visões sejam elementos
distintos, e provavelmente também que “tabelas” sempre signifiquem especificamente
tabelas de base e que tabelas de base sejam fisicamente armazenadas e visões não.
Porém todo o sentido de uma visão é o de que ela é uma tabela (ou, como eu preferiria
dizer, uma relação); ou seja, podemos efetuar os mesmos tipos de operações em visões
que podemos efetuar em relações regulares (pelo menos no modelo relacional), pois
visões são “relações regulares”. Ao longo deste livro, portanto, utilizarei o termo relação
para representar uma relação (possivelmente uma relação de base, possivelmente uma
visão, possivelmente um resultado de consulta, e assim por diante); e, se quiser me
referir a uma relação de base especificamente, direi “relação de base”. Recomendação:
sugiro veementemente que você adote a mesma disciplina. Não caia na armadilha
habitual de pensar que o termo relação significa especificamente uma relação de
base – ou, em termos SQL, de pensar que o termo tabela significa especificamente
uma tabela de base. Da mesma forma, não caia na armadilha habitual de pensar que
relações de base (ou tabelas de base, em SQL) têm de ser fisicamente armazenadas.
Relações versus relvars
Agora, é inteiramente possível que você já soubesse tudo que vim lhe dizendo até
aqui neste capítulo; aliás, até espero que você saiba, apesar de também esperar que
isso não signifique que você tenha achado o material maçante. De qualquer forma,
agora abordarei algo que você pode ainda não conhecer. O fato é que historicamente
tem havido muita confusão sobre mais uma diferença lógica: mais precisamente,
aquela entre relações como tais por um lado, e variáveis de relações (relation variables)
por outro.
Esqueça os bancos de dados por um momento; considere, em vez disso, o simples
exemplo de linguagem de programação a seguir. Vamos supor que eu diga, em alguma
linguagem de programação:
DECLARE N INTEGER ... ;
14 Digo isso totalmente consciente de que a maioria dos produtos SQL de hoje de fato fornece opções
para operações de hash, particionamento, indexação, agrupamento, entre outras formas de orga-
nização dos dados armazenados em disco. Apesar dessa situação, ainda considero o mapeamento
entre tabelas de base e armazenamento físico nesses produtos como razoavelmente direto.
49Capítulo 1 ■ Preparando o cenário
Então, N aqui não é um inteiro. Em vez disso, ele é uma variável, cujos valores são in-
teiros como tais –inteiros diferentes em momentos distintos. Todos nós entendemos
isso. Bem, exatamente da mesma forma, se digo em SQL
CREATE TABLE T ... ;
então T não é uma tabela. Ela é uma variável, uma variável de tabela ou (como preferiria
dizer, ignorando diversas peculiaridades SQL tais como linhas duplicadas e ordena-
ção de colunas da esquerda para a direita) uma variável de relação, cujos valores são
relações como tais (relações diferentes em momentos distintos).
Dê mais uma olhada na figura 1.3 – o banco de dados de fornecedores e peças. Essa
figura mostra três valores – mais especificamente, valores de relação que chegam a
existir no banco de dados em algum momento específico. No entanto, se fôssemos
verificar o banco de dados em algum momento distinto, provavelmente veríamos três
valores de relação diferentes sendo mostrados no lugar deles. Em outras palavras, S, P
e SP nesse banco de dados são realmente variáveis: variáveis de relação, para sermos
precisos. Por exemplo, vamos supor que a variável de relação S atualmente tenha o valor
mostrado na figura 1.3 – o valor de relação, quer dizer – e vamos supor que excluamos
o conjunto de tuplas (na realidade há apenas uma) para fornecedores em Atenas:
DELETE S WHERE CITY = 'Athens' ;
Aqui está o resultado:
Conceitualmente, o que aconteceu aqui é que o valor