You are on page 1of 7

GeneXus e Bases de Dados Relacionais: a essência

Uma introdução simples


Por Breogán Gonda e Nicolás Jodal
Versão 1, Montevidéu, 16 de agosto de 2007

Muitas vezes, acredita-se que as Bases de Dados Relacionais são especialmente


complexas e difíceis de entender. As Bases de Dados Relacionais foram introduzidas
por Edgar F. Codd em 1970 com dois propósitos principais: representação simples dos
dados e operadores poderosos para manipular esses dados de uma maneira automática e
simples.
Hoje todas as aplicações computacionais de negócios se desenvolvem em torno de bases
de dados relacionais. Mas nem sempre foi assim.
O conceito de base de dados e o primeiro sistema de gerenciamento de base de dados
foram introduzidos na primeira metade da década de 60 por Charles Bachman. Poucos
anos depois, existiam no mercado vários sistemas de gerenciamento de bases de dados
baseados em diferentes idéias e estruturas: havia uma tendência geral à casuística.
No ano 1970 foi publicado o trabalho teórico fundamental de Edgar F. Codd sobre as
bases de dados relacionais. Mas a adoção generalizada destas bases de dados relacionais
se estabelece só na primeira metade da década de 90.
Antes, os dados eram armazenados em múltiplos arquivos independentes entre si e tanto
o cuidado da consistência quanto a navegação de uns dados para outros estavam dentro
dos programas.
A grande mudança é que a Base de Dados Relacional é, em princípio, um único lugar
onde colocar os dados e, paralelamente, descreve esses dados e contém regras que
devem ser obedecidas para utilizá-los e operadores que nos ajudam no seu uso. Ou seja,
em vez de ficar tudo nas mãos do programador, muitas tarefas importantes de
administração (idealmente todas) e de navegação nos dados são realizadas em forma
automática pelo Sistema de Gerenciamento de Base de Dados.
GeneXus foi construído a partir destas idéias, de seu aprimoramento e aperfeiçoamento.

Bases de Dados Relacionais


Numa Base de Dados Relacional, os dados são armazenados em “Relações” que a
efeitos desta introdução, consideraremos como tabelas. Cada tabela tem um conjunto de
colunas, cada uma das quais representa diferentes valores para um certo elemento de
dados uniforme (com um significado bem determinado, como por exemplo:
CodigoCliente, NomeCliente, CodigoProduto, DescriçãoProduto), que chamaremos
“Atributo”.
Cada fileira combina valores de diferentes atributos.
Com conjuntos destas simples tabelas são armazenados todos os dados.
Vejamos um pequeno exemplo

1
Mas não devemos pensar em tabelas isoladas (pois voltaríamos para os tempos dos
arquivos múltiplos independentes).
Qual é a diferença essencial entre estas “tabelas relacionais” e os arquivos
independentes?
A homogeneidade das colunas em torno de um significado bem definido para cada uma
delas, o fato de cada coluna estar descrita exteriormente. Mas, um atributo estará
presente apenas numa tabela? Em certos casos sim, em outros não. Vamos supor
CodigoCliente, parece razoável encontrá-lo numa tabela onde temos todos os dados do
Cliente. Por sua vez, parece razoável que CodigoCliente identifique essa tabela no
sentido de não haver mais de uma fileira com o mesmo valor de CodigoCliente.
Diremos neste caso que CodigoCliente é a “chave” da tabela que contém os dados fixos
dos clientes, tabela que, por exemplo, chamaremos “Clientes”.
Também parece razoável que não exista mais de uma tabela para armazenar os dados
fixos dos Clientes: não haverá mais de uma tabela com a mesma chave.
Mas haverá outras tabelas onde aparecerá o atributo CodigoCliente, por exemplo, uma
na qual são armazenadas as faturas. Cada Fatura estará ligada a um Cliente. Como se
opera essa vinculação? Através do CodigoCliente.
Então, existem atributos que podem aparecer em múltiplas tabelas. Estes atributos
aparecendo em mais de uma tabela serão chamados de atributos primários.
Parece razoável existirem atributos que podem aparecer numa única tabela (vamos
supor por um momento que o NomeCliente só aparece na tabela de Clientes). Estes
atributos aparecendo apenas em uma tabela, em toda a base de dados, serão
chamados de atributos secundários.

2
Significado dos atributos e URA: Universal Relational Assumption
Um modelo geralmente tem elementos semânticos e elementos sintáticos. É fácil operar
com elementos sintáticos, porém, como representar os elementos semânticos de modo
que seja fácil operar com eles? Ou, de outro modo, como representar os elementos
semânticos por meio de elementos sintáticos? Uma boa maneira de fazê-lo é
representando os significados dos atributos mediante seus nomes. Para isso é essencial
uma muito boa atribuição de nomes aos atributos.
Como atribuímos os nomes aos atributos? O essencial é que o nome atribuído represente
bem o significado do atributo, com a maior independência possível do lugar no qual
aparece na Base de Dados.
Que tal supor que existe uma super tabela que contém todas as tabelas de nossa Base de
Dados Relacional? Como na realidade em nossa base de dados precisaremos de
múltiplas tabelas, esta super tabela não será nem densa nem homogênea, mas cada
coluna responderá sempre a um atributo: em certa forma, a cada coluna associamos um
significado que é o mesmo para todas as tabelas em que essa coluna estiver envolvida.
O que se tenta conseguir é que um determinado atributo tenha sempre o mesmo nome,
independentemente do lugar no qual aparece, e que não existam dois atributos diferentes
com o mesmo nome. Eis a essência da URA e representa uma muito boa base para
estabelecer uma nomenclatura dos atributos. GeneXus assume o uso da URA (em rigor
de uma URA ampliada).
Vejamos um pequeno exemplo de URA

Normalização
Nos trabalhos de Edgar F. Codd é introduzida a Normalização a efeitos de evitar um
conjunto de anomalias e permitir uma representação sem problemas. Os dados podem
não cumprir com forma normal alguma ou estar em 1ª Forma Normal ou em 2ª Forma
Normal ou em 3ª Forma Normal. É desejável que os dados estejam em 3ª Forma
Normal. Doravante, ao falar “normalizar os dados” estaremos nos referindo a
representá-los em 3ª Forma Normal.

3
Mas, qual é a essência da normalização? É obter uma representação não redundante dos
dados. Se a representação fosse redundante, haveria duas ou mais versões do mesmo
dado e, se não existir controles muito robustos sobre eles, fatalmente se acabará numa
inconsistência e existirão várias versões do mesmo dado com valores diferentes. O que
se deseja obter com a normalização é que exista uma única versão de cada dado, ou seja,
não armazenar um dado que possa se inferir do resto dos dados armazenados..
E é tudo o que precisamos saber da normalização. Como fazê-la? GeneXus a faz para
nós automaticamente e sem erros.

Integridade Referencial
Dissemos que nossa Base de Dados está composta por um conjunto de tabelas. Como se
relacionam essas tabelas? Pelos valores de seus atributos primários.
Se olharmos o exemplo que colocamos para explicar a URA, poderemos ver que cada
Cliente que aparece na tabela Fatura aparece também na tabela Clientes, que cada
Produto que aparece na tabela Linhas de Faturas aparece também na tabela Produtos
e que cada Fatura que aparece na tabela Linhas de Faturas aparece também na tabela
Fatura.
Nada disto é coincidência: se existisse uma Fatura envolvendo um Cliente não
catalogado na tabela Clientes, iria se produzir uma inconsistência (o mesmo ocorreria
nos outros exemplos). Tudo isto se engloba numa lei fundamental de consistência que
podemos enunciar da seguinte forma:
Se o atributo A é chave em uma determinada tabela T1 e aparece também em outra
tabela T2, para que exista uma determinada linha de T2, deve existir em T1 uma linha
com o mesmo valor de A.
Nos exemplos consideramos atributos simples, mas tudo o que antecede cumpre-se
também para atributos compostos.
Estas regras de integridade referencial devem ser obedecidas para garantir a
consistência do modelo.

Considerações acerca do que antecede


Basicamente, toda a teoria precedente deve-se a Edgar F. Codd. Entretanto, em seus
trabalhos fundamentais Codd omitiu duas coisas importantes:
• A introdução da URA. O conceito da URA é essencial à teoria relacional de
Codd, provavelmente foi tão evidente para ele que por isso não o enunciou.
• Também, por razões que não são simples de compreender, Codd não introduziu
em seus trabalhos fundamentais os conceitos de Integridade Referencial. Vários
anos depois os introduziu, mas de uma maneira empírica, sem utilizar a simples
regra de integridade referencial que enunciamos.
Podemos dizer sem equivocar-nos que os grandes objetivos de Codd eram obter uma
representação simples dos dados e prover operadores para manipular automaticamente
esses dados. GeneXus implementa automaticamente esses operadores.

Ampliações de GeneXus à teoria relacional


Na construção de GeneXus, foi necessário fazer algumas ampliações à teoria relacional
que, com certeza, são totalmente consistentes com a mesma.

4
Basicamente, três são estas ampliações: ampliação da URA a efeitos de permitir a
representação de Subtipos, Introdução de Fórmulas e Introdução de Redundâncias.

SubTipos

Freqüentemente encontramos determinados atributos como, por exemplo,


AeroportoSaida, AeroportoChegada que têm um significado concreto bem
determinado mas que, por sua vez, são casos particulares de um atributo mais geral
(Aeroporto). Alguém diria que eles têm o mesmo significado básico, e portanto é o
mesmo atributo em diferentes papéis mas, o que ocorre quando dois ou mais aparecem
juntos? Não poderíamos trabalhar sem diferenciá-los. Assim, diremos que
AeroportoSaida é um Subtipo de Aeroporto e que AeroportoChegada é um Subtipo
de Aeroporto. Este conceito de subtipos não se limita a atributos atômicos e pode se
aplicar a grupos de atributos

Fórmulas
Se temos, por exemplo, que ValorLinhaFatura = QuantidadeVendida * PreçoVenda e
que SubTotalFatura = Σ ValorLinhaFatura, devemos armazenar na Base de Dados
ValorLinhaFatura e SubTotalFatura?
Precisamos uma representação tão completa como possível, mas sempre consistente.
Se não temos fórmulas a resposta é: sim, devemos armazená-los.
Se trabalhamos em nível superior e temos fórmulas em nosso modelo, nem
SubTotalFatura nem ValorLinhaFatura devem ser armazenados porque o sistema é
capaz de calculá-los quando necessário (e os valores armazenados seriam redundantes
dos que podemos calcular a qualquer momento e, eventualmente, poderiam chegar a ser
inconsistentes).
GeneXus introduz um conjunto amplo e poderoso de fórmulas.

Redundâncias
São boas ou ruins as redundâncias? Pelo que se viu até agora, pareceria que são ruins (já
que poderiam ser uma fonte de inconsistências). Na realidade, as redundâncias não são
nem boas nem ruins, as verdadeiramente ruins são as “redundâncias não controladas”.
Se assumimos explicitamente uma redundância e estabelecemos mecanismos de
controle de maneira a manter os dados sempre consistentes, a redundância não tem
efeitos prejudiciais.
Poderá uma redundância ter bons efeitos? Podemos acreditar que ter um atributo
armazenado nos poupa o tempo de calculá-lo. Às vezes esse tempo é irrelevante: por
exemplo, guardar como redundante o atributo ValorLinhaFatura só para poupar o
cálculo ValorLinhaFatura = QuantidadeVendida * PreçoVenda não parece razoável com
a tecnologia de hoje (entretanto, sim o teria sido há 40 anos, quando uma operação
aritmética tão simples como esta comportava tempos importantes). Porém, um caso
diferente é o de guardar redundante SubTotalFatura = Σ ValorLinhaFatura. Se este
atributo for utilizado com certa freqüência e a quantidade de elementos adicionados for
grande (devem acessar-se muitos registros para fazer a adição) mantê-lo redundante
pode ser muito proveitoso.
Como trata GeneXus as redundâncias? GeneXus nos permite introduzir certas
redundâncias. Uma vez feito o anterior, para cada redundância, GeneXus se

5
responsabiliza pela manutenção da consistência e a aproveita quando convém para
melhorar a performance.

Operadores
Codd optou em seu momento por operadores explícitos que são bastante potentes mas
requerem, por parte do usuário, de muito conhecimento da Base de Dados, o que era
possível naqueles tempos, quando uma base de dados constava de umas poucas tabelas,
e inviável com as grandes bases de dados de hoje.
Assim, utilizando a sintaxe da linguagem SQL (Structured Query Language,
desenvolvido pela IBM diretamente a partir dos trabalhos de Codd), se voltarmos ao
exemplo colocado para introduzir o URA, caso desejemos listar para cada cliente suas
faturas e para cada fatura suas linhas, deveremos fazer algo do tipo:
Select Clientes.Cliente, NomeCliente, Faturas.Fatura, DataFatura,
Produtosd.Produto, DescriçãoProduto, QuantidadeVendida
From Clientes, Faturas, LinhasFaturas, Produtos
Where Clientes.Cliente = Faturas.Cliente and
Faturas.Fatura=LinhasFaturas.Fatura and
LinhasFaturas.Produto=Produtos.Produto
Order by Cliente, Fatura, Produto
Esta maneira de escrever é muito pesada (com o Select declaramos as colunas da saída,
com o From as tabelas das quais devem se obter os dados, com o Where a maneira em
que devem se combinar tabelas e com o Order By a ordem da saída) e quando a base de
dados tiver 1000 tabelas em vez de umas poucas, não haverá, por exemplo, nenhuma
possibilidade de que os usuários possam escrever estas consultas.
Com os conceitos que introduzimos aqui, o que antecede poderia se escrever de uma
maneira corriqueira:
Select Cliente, NomeCliente, Fatura, DataFatura, Produto, DescriçãoProduto,
QuantidadeVendida
Order by Cliente, Fatura, Produto
onde simplesmente listamos as colunas de saída na ordem em que as queremos e
determinamos a ordem das linhas dessa saída porque o sistema conhece todo o resto.
No GeneXus optamos por operadores implícitos de muito alto nível que permitem, por
um lado, escrever as consultas de forma muito simples e, por outro, que as mencionadas
consultas sejam independentes das tabelas onde estão os dados: nunca referimos a
tabelas e é o sistema que determina em tempo de geração quais tabelas deve utilizar.
Esta é uma característica muito importante porque não existem as Bases de Dados
estáveis, sempre há modificações e, muitas vezes, um atributo passa de umas tabelas
para outras. A especificação da consulta GeneXus continuará válida, a especificação
SQL, não.

Resumo
GeneXus supõe o uso de uma Base de Dados Relacional e caso ela exista, é usada para
armazenar os dados e utiliza seus operadores sempre que possível.

6
Entretanto, vai muito além das Bases de Dados Relacionais: pega essas bases de dados e
as provê de inteligência, constituindo um poderoso sistema de administração automática
do conhecimento (e conseqüentemente dos dados sobre que esse conhecimento trata).
Como tal, utiliza as Bases de Dados e os serviços que possam estar disponíveis de uma
maneira ótima e se amanhã as Bases de Dados Relacionais forem substituídas por
qualquer sistema de armazenamento de dados (e provisão de serviços) que tiverem
como objetivo uma representação não redundante, consistente, eficiente e que privilegie
a acessibilidade dos dados, GeneXus seguirá gerando e mantendo em forma inteligente
sistemas para esses dados.

You might also like