UNIVERSIDADE FEDERAL DE MATO GROSSO DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO COORDENAÇÃO DE ENSINO DE GRADUAÇÃO BANCO DE DADOS TEMPORAIS: Teoria e prática RAPHAEL VIANA ITACARAMBY CUIABÁ-MT 2006 UNIVERSIDADE FEDERAL DE MATO GROSSO DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO COORDENAÇÃO DE ENSINO DE GRADUAÇÃO BANCO DE DADOS TEMPORAIS: Teoria e prática RAPHAEL VIANA ITACARAMBY Monografia apresentado ao Departamento de Ciência da Computação da Universidade Federal de Mato Grosso, para obtenção do Título de Bacharel em Ciência da Computação. Orientador: Prof. Custódio Gastão da Silva Júnior. CUIABÁ-MT 2006 UNIVERSIDADE FEDERAL DE MATO GROSSO DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO COORDENAÇÃO DE ENSINO DE GRADUAÇÃO CERTIFICADO DE APROVAÇÃO BANCO DE DADOS TEMPORAIS: Teoria e prática Raphael Viana Itacaramby Orientador: Prof. Custódio Gastão da Silva Júnior Aprovado em 11 de setembro de 2006. __________________________________________________________________ Prof. Custódio Gastão da Silva Júnior Prof. Departamento de Ciência da Computação/ICET/UFMT (Orientador) __________________________________________________________________ MSc. Luciana Correia Lima de Faria Borges Profª. Departamento de Ciência da Computação/ICET/UFMT __________________________________________________________________ Prof. Moisés Bites Borges de Castro Bacharel em Ciência da Computação – Pós-graduado em Psicanálise Clínica A DEUS por me ajudar, me capacitar, me motivar, mesmo quando parecia que eu não ia conseguir e quando já estava pensando em desistir de novo. DELE, por ELE e para ELE minha vida e gratidão. A minha família, sem a qual não teria estrutura; sem a qual, com certeza, não estaria aqui hoje. A minha amada noiva, Thais, que me apoiou, mesmo quando eu desisti das outras vezes e que orou por mim. AGRADECIMENTOS Ao meu orientador, à minha família, minha noiva e principalmente a DEUS. Obrigado SENHOR JESUS. RESUMO O presente trabalho enfoca bancos de dados temporais e através de pesquisa bibliográfica procura mostrar seus principais conceitos. Compara dois sistemas gerenciadores de bancos de dados, o Oracle e o PostgreSQL com a teoria de bancos de dados temporais para avaliar o que da teoria tem sido implementado por eles. Palavras-chave: Banco de dados temporais; Oracle; PostgreSQL ABSTRACT The present work focuses temporal databases and bibliographical research search to show its main concepts. It compares two database management system, the Oracle and the PostgreSQL, with the theory of temporal databases to evaluate what of the theory he has been implemented for them. Keywords: Temporal databases; Oracle; PostgreSQL LISTA DE ILUSTRAÇÕES ILUSTRAÇÃO 1 - REPRESENTAÇÃO DOS DADOS EM DUAS DIMENSÕES.................... 17 ILUSTRAÇÃO 2 - REPRESENTAÇÃO DOS DADOS COM DIMENSÃO TEMPORAL..........18 ILUSTRAÇÃO 3 - INSTANTE “AGORA”.................................................................................20 ILUSTRAÇÃO 4 - INTERVALO TEMPORAL..........................................................................21 ILUSTRAÇÃO 5 - ELEMENTO TEMPORAL.......................................................................... 22 LISTA DE TABELAS TABELA 1 - TABELA DE CLIENTES......................................................................................15 TABELA 2 - TABELA DE CLIENTES ALTERADA..................................................................15 TABELA 3 - TABELA DE CLIENTES COM ATRIBUTO TEMPORAL.................................... 16 TABELA 4 - TABELA DE FUNCIONÁRIOS COM ELEMENTO TEMPORAL.........................24 TABELA 5 - TIPOS DE DADOS SUPORTADOS PELO POSTGRESQL...............................37 TABELA 6 - VALORES ESPECIAIS PARA DATA E HORA................................................... 38 TABELA 7 - TABELA DE CLIENTES BITEMPORAL............................................................. 42 TABELA 8 - TABELA DE CLIENTES COM TIMESTAMPS.................................................... 44 TABELA 9 - TABELA DE CLIENTES COM TIMESTAMPS ALTERADA................................44 TABELA 10 - TABELA DE FUNCIONÁRIOS..........................................................................55 TABELA 11 - TABELA DE FAIXAS SALARIAIS..................................................................... 55 TABELA 12 - TABELA DE DEDUÇÕES................................................................................. 56 TABELA 13 - TABELA QUE RELACIONA DEDUÇÕES E FAIXAS SALARIAIS................... 56 SUMÁRIO RESUMO..................................................................................................................... 6 ABSTRACT................................................................................................................. 6 1 INTRODUÇÃO....................................................................................................... 10 1.1 OBJETIVOS.................................................................................................... 11 1.1.1 Objetivo Geral.......................................................................................... 11 1.1.2 Objetivos específicos............................................................................... 11 1.2 JUSTIFICATIVA.............................................................................................. 12 1.3 HIPÓTESES................................................................................................... 12 1.4 METODOLOGIA............................................................................................. 13 1.5 CRONOGRAMA PROPOSTO........................................................................ 13 2 FUNDAMENTAÇÃO TEÓRICA............................................................................. 15 1.1 CONCEITOS DE REPRESENTAÇÃO TEMPORAL....................................... 17 2.1 ELEMENTOS PRIMITIVOS DA REPRESENTAÇÃO TEMPORAL................ 19 2.1.1 Instante no tempo.................................................................................... 19 2.1.2 Intervalo temporal.................................................................................... 20 2.1.3 Elemento temporal.................................................................................. 22 2.1.4 Duração temporal.................................................................................... 24 2.1.5 Fluxo do tempo........................................................................................ 24 2.1.5.1 Tempo totalmente ordenado............................................................ 25 2.1.6 Tempo absoluto e tempo relativo............................................................ 25 2.1.7 Tempo de transação e tempo válido....................................................... 26 2.1.8 Representação do tempo........................................................................ 27 2.2 CLASSIFICAÇÃO DOS BANCOS DE DADOS TEMPORAIS........................ 27 2.3 CONSULTAS A BANCOS DE DADOS TEMPORAIS.....................................28 2.3.1 Problemas no processamento de consultas temporais........................... 29 2.4 MODELOS DE DADOS TEMPORAIS............................................................ 31 2.4.1 Modelo temporal TRM............................................................................. 32 2.4.2 A linguagem de consulta do TRM............................................................ 33 2.5 OPERAÇÕES BÁSICAS SOBRE BANCOS DE DADOS TEMPORAIS......... 34 3 POSTGRESQL...................................................................................................... 35 3.1 Tipos de dados para data e hora.................................................................... 36 3.2 O PostgreSQL e a implementação de aspectos da teoria de bancos de dados temporais............................................................................................................... 37 3.2.1 Bi-Temporal PostgreSQL........................................................................ 38 3.2.2 Time travel no PostgreSQL..................................................................... 42 4 ORACLE................................................................................................................ 45 4.1 Tipos de dados para data e hora.................................................................... 45 4.1.1 O Oracle e a implementação de aspectos da teoria de bancos de dados temporais........................................................................................................... 46 4.1.1.1 Workspace Manager........................................................................ 46 5 ESTUDO DE CASO............................................................................................... 53 5.1 Implementando no Oracle.............................................................................. 55 5.2 Implementando no PostgreSQL...................................................................... 56 6 CONSIDERAÇÕES FINAIS................................................................................... 59 REFERÊNCIAS......................................................................................................... 61 9 1 INTRODUÇÃO Um banco de dados é uma coleção organizada de dados que são manipulados por um computador. Diversos tipos de dados podem ser armazenados em um banco de dados, desde valores relativos a movimentações bancárias, até imagens. Geralmente, quando os dados relativos a um determinado registro se alteram, os anteriores são sobrescritos, desperdiçando uma informação que poderia ser útil. Isso significa que apenas o estado atual da realidade é capturado e não há idéia de como caminharam, de como evoluíram os dados até aquele momento. Então o que fazer para não perder o histórico dos dados? A resposta é associar o tempo a eles. Quando estes dados vigoraram? Eles ainda são válidos? Até quando serão válidos? Essas perguntas podem ser respondidas através dos bancos de dados temporais. Eles são bancos de dados que nunca sobrepõe informações antigas e que possuem mecanismos para o facilitar o tratamento do tempo associado aos dados. O tempo é tratado implicitamente pelo banco, isto é, ele é que tem que se preocupar com a forma como vai gerenciar os dados antigos, os novos e a forma de dar respostas às consultas desejadas pelo usuário. Os bancos de dados temporais já são matéria de pesquisa e estudos diversos há alguns anos. Segundo Nina Edelweiss (1998): Embora as pesquisas em BD temporais se estendam já por mais de 20 anos, poucos sistemas realmente utilizáveis existem. Existem, sim, várias experiências sob forma de protótipos, nos quais se baseiam estudos de problemas encontrados (de armazenamento e recuperação de informações), e mapeamentos de modelos temporais para BD tradicionais, nos quais os rótulos temporais são explicitamente representados e manipulados. Apesar de toda essa pesquisa em torno do tema, não temos certeza de quais 10 aspectos da teoria relacionada aos bancos de dados temporais os SGBDs atuais chegaram a implementar na prática. Podemos verificar que, se não houver tratamento de informação temporal de forma implícita, é possível trabalhar com ela de forma explícita, mas até que ponto os sistemas de banco de dados atuais chegaram é a questão. Partindo desse princípio, pretende-se fazer uma verificação de como dois SGBDs (um comercial e outro de código aberto) tratam os aspectos temporais dos dados por eles armazenados, e assim, comparar aquilo apresentado na teoria com o que está atualmente disponível na prática. 1.1 OBJETIVOS 1.1.1 Objetivo Geral O objetivo deste trabalho é estudar os aspectos teóricos dos bancos de dados temporais e verificar se dois SGBDs (Oracle e PostgreSQL) implementam, mesmo que parcialmente, os conceitos presentes na teoria. 1.1.2 Objetivos específicos Estudar os bancos de dados temporais e descobrir como eles tratam o tempo associado aos dados por eles armazenados e gerenciados. Verificar o que da teoria de bancos de dados temporais é aplicado em dois SGBDs comerciais – Oracle e PostgreSQL 11 1.2 JUSTIFICATIVA Os bancos de dados costumam trabalhar com os dados atualizados, desprezando valores antigos, que um dia foram válidos e representaram um momento na história dos mesmos. Um banco de dados com essas características não proporciona uma visão dinâmica da informação, não permite saber como ela era, apenas como ela é, fazendo com que seja mostrado apenas um instantâneo da realidade. Já os bancos de dados temporais fornecem um modo de tratar os dados e armazenar sua história. É uma maneira de analisar a evolução de um conjunto de dados, tentar estabelecer padrões de comportamento e assim fazer análises que apontem para um caminho no futuro. Existem estudos teóricos sobre bancos de dados temporais, mas até que ponto a teoria tem sido implementada? Quais os recursos que temos disponíveis hoje para tratar dados associados ao tempo? Essas questões merecem ser respondidas e é isso que pretendo fazer neste trabalho tomando como base dois bancos de dados conhecidos: o Oracle e o PostgreSQL 1.3 HIPÓTESES Os bancos de dados temporais são objeto de estudo, mas não há implementação dessa teoria na prática, o que pretendo mostrar através do estudo de dois SGBDs conhecidos: o Oracle e o PostgreSQL 12 1.4 METODOLOGIA O trabalho será desenvolvido a partir de pesquisa bibliográfica envolvendo o tema proposto e do estudo da documentação dos dois SGBDs escolhidos para a pesquisa (Oracle e PostgreSQL), permitindo a comparação e o traçado de um panorama atualizado do que está sendo aplicado na prática em relação ao tratamento de aspectos temporais dos dados. 1.5 CRONOGRAMA PROPOSTO Etapas 2 Julho 3 4 MESES/SEMANAS Agosto 1 2 3 4 1 Setembro 2 3 Etapa 1 Etapa 2 Etapa 3 Etapa 4 Etapa 5 Etapa 1 - Revisão Bibliográfica Leitura de livros e artigos sobre o tema da monografia. Etapa 2 – Estudo dos SGBDs Oracle e PostgreSQL Estudo de manuais, guias de referência, ou qualquer outro material disponível sobre tais sistemas gerenciadores de bancos de dados. Etapa 3 - Redação Preliminar Redação do texto da monografia. 13 Etapa 4 - Redação Final Conclusão e revisão do texto. Etapa 5 – Apresentação do trabalho Apresentação do trabalho. 14 2 FUNDAMENTAÇÃO TEÓRICA Um sistema de banco de dados é um sistema que através do computador manipula e organiza registros, tornando-os disponíveis ao usuário. (DATE, 1990, p. 2). Ele permite ao usuário a realização de diversas operações sobre esses registros, tais como a consulta, a atualização de valores, a remoção e a inserção de novos registros. Normalmente um sistema de banco de dados contém apenas a versão mais atualizada de cada um dos registros armazenados. Os dados antigos são sobrescritos através das operações de atualização, fazendo com que o banco de dados represente a realidade capturada por ele como um instantâneo. Tomemos como exemplo a tabela de clientes abaixo. Uma simples alteração no endereço do cliente 'João da Silva' faria com que seu endereço anterior fosse perdido. TABELA 1-TABELA DE CLIENTES id_cliente nome_cliente endereco_cliente 1 João da Silva Rua Alpha, 123 2 Janete Cunha Rua Gama, 456 Depois da alteração temos a mesma tabela atualizada, mas com o endereço antigo de 'João da Silva' descartado: TABELA 2 - TABELA DE CLIENTES ALTERADA id_cliente nome_cliente endereco_cliente 1 João da Silva Rua Beta, 789 2 Janete Cunha Rua Gama, 456 Os bancos de dados temporais são diferentes porque não tratam apenas dos 15 dados, mas agregam o tempo a eles. Os valores antigos são preservados com o auxílio de rótulos temporais que lhes conferem um caráter de informação válida em determinado momento da história. Ainda usando o exemplo anterior, ao alterar o endereço de 'João da Silva' em um banco de dados temporal os resultados poderiam ser os seguintes: TABELA 3 - TABELA DE CLIENTES COM ATRIBUTO TEMPORAL id_cliente nome_cliente endereco_cliente dataInsercao_cliente 1 João da Silva Rua Alpha, 123 12/08/2005 1 João da Silva Rua Beta, 789 27/06/2006 2 Janete Cunha Rua Gama, 456 11/02/2006 Pode-se verificar que o mesmo cliente tem agora dois registros, com endereços diferentes e datas de inserção diferentes. O registro com data de inserção mais recente representa o estado corrente armazenado pelo banco. Dessa forma, dados temporais são associados aos dados armazenados, identificando quando a informação foi inserida, ou alterada, ou mesmo qual o seu o tempo de validade. É desejável que o tratamento dos dados temporais seja transparente, ou seja, que o banco de dados manipule os dados temporais automaticamente. “Um banco de dados Temporal é aquele que apresenta alguma forma implícita de representação de informações temporais.” (EDELWEISS, 1998). A história dos bancos de dados temporais pode ser dividida em três períodos marcantes: de 1956 a 1978 quando houve o desenvolvimento dos modelos conceituais; de 1978 a 1990, onde surgiram várias linguagens de consulta temporal; e de 1988 em diante quando predomina uma preocupação com a implementação e estruturas de armazenamento. (AMO, 1997, p. 2) Seu estudo foi motivado porque há determinadas situações envolvendo dados 16 temporais que são difíceis de serem tratadas pelos SGBDS convencionais, mas que são facilmente gerenciados por bancos de dados temporais. Agora segue uma explanação sobre os principais conceitos envolvendo bancos de dados temporais. 1.1 CONCEITOS DE REPRESENTAÇÃO TEMPORAL Os modelos de dados tradicionais apresentam duas dimensões: 1) a dos atributos, 2) a das instâncias dos dados (tuplas). Imaginamos tal representação como dois eixos de um plano. ILUSTRAÇÃO 1 - REPRESENTAÇÃO DOS DADOS EM DUAS DIMENSÕES O tempo é introduzido no banco de dados como uma nova dimensão, levanos a representar os dados com atributos em um eixo, as tuplas em outro e o tempo que age sobre cada uma das tuplas num terceiro eixo, como pode ser visto na figura 2. 17 ILUSTRAÇÃO 2 - REPRESENTAÇÃO DOS DADOS COM DIMENSÃO TEMPORAL A dimensão tempo pode ser representada de várias formas, levando-se em consideração alguns aspectos fundamentais: a natureza do tempo, sua estrutura matemática e granulidade. Quanto à natureza, supõe-se que o tempo seja contínuo. Sua representação é isomórfica a uma reta imaginária na qual, tomados quaisquer pontos dois a dois, existem infinitos pontos entre eles. ILUSTRAÇÃO 3 - EIXO TEMPORAL Apesar de sua natureza contínua, ele pode ser visto como discreto para simplificar sua representação. Encará-lo dessa maneira facilita a implementação de 18 modelos temporais, por isso, no contexto de bancos de dados costuma-se tratar o tempo como sendo pontual (AMO, 1997), representando pontos discretos numa linha imaginária, isomórfica à reta dos números inteiros. Os intervalos entre os pontos no tempo são de igual duração, indivisíveis e recebem o nome de chronons. Quando o tempo é discreto, os pontos no tempo se dispõem da forma descrita a seguir: − variação ponto a ponto: o tempo só é válido em instantes definidos, não sendo considerado nos outros instantes; − variação por escada: o tempo permanece constante desde o ponto em que foi definido até o momento em que seja definido outro valor no tempo. Geralmente corresponde a uma variação baseada em eventos; − variação temporal definida por uma função: uma função é usada para definir valores, onde eles não são expressamente definidos, através de interpolação. A granulidade do tempo refere-se às unidades usadas na contagem do tempo. Por exemplo, ela pode ser feita em anos, meses, dias ou horas, ou ainda, todos eles. Cada partícula desse sistema para contagem do tempo corresponde à duração de um chronon (EDELWEISS, 1998). 2.1 ELEMENTOS PRIMITIVOS DA REPRESENTAÇÃO TEMPORAL 2.1.1 Instante no tempo A definição de instante no tempo depende da variação temporal adotada. Se o tempo for contínuo o instante no tempo é um valor infinitesimal na reta temporal. 19 Essa representação é análoga à dos números reais, isso significa que, entre dois instantes quaisquer no tempo, existe um número infinito de pontos. Caso seja considerada a variação discreta no tempo um instante é representado por um chronon. Um evento ocorre num tempo t, se ocorre em qualquer tempo durante o chronon representado por t. Por exemplo, se o chronon utilizado em um banco de dados tem duração de um dia, toda alteração realizada a qualquer hora do dia 02 de maio será gravada como relacionada à data 02 de maio. Para o sistema não interessaria a hora em que ocorreu a alteração, mas o dia em que ela ocorreu. Na variação do tempo de forma linear temos também um instante especial: agora, ou now. Ele representa o instante presente e está em constante movimento na reta temporal. Qualquer instante anterior ao agora é considerado passado e qualquer instante posterior, futuro. ILUSTRAÇÃO 3 - INSTANTE “AGORA” 2.1.2 Intervalo temporal Um intervalo temporal é um conjunto de pontos no tempo consecutivos. Na variação contínua, cada intervalo tem um número infinito de instantes. Na variação discreta há um número finito de pontos dentro de cada intervalo temporal. Sua duração é especificada através de seus limites superior e inferior, os quais podem 20 ou não estar incluídos no intervalo. ILUSTRAÇÃO 4 - INTERVALO TEMPORAL No intervalo acima os limites inferior e superior são, respectivamente, os instantes A e B do eixo temporal. Eles podem, ou não estar fazer parte do intervalo temporal. Quando um dos pontos que delimitam o intervalo é o instante agora tem-se um intervalo especial, cuja duração varia com o passar do tempo. Intervalos temporais podem ser representados da seguinte maneira: [A, B], onde A é o limite inferior e B o limite superior. O próprio eixo temporal pode ser considerado um intervalo de tempo, representado por [<<, >>] onde os símbolos << e >> representam o início e o fim da contagem do tempo, respectivamente. Um intervalo temporal permite representar uma certa quantidade de pontos consecutivos no tempo, ou mesmo um instante no tempo. No caso do intervalo [A, B], se o instante A for igual ao instante B ocorre um intervalo que equivale a um ponto no tempo. Assim, chega-se a conclusão que, para qualquer intervalo temporal uma das duas relações a seguir tem que ser verdadeira envolvendo os instantes A e B: A < B ou A = B. Através dos operadores first e last podemos extrair o primeiro e último elemento de um intervalo (que é totalmente ordenado pela relação before). 21 Seja I, um intervalo de tempo e I ⊂ T, então: first ( I ) é o elemento t pertence a I tal que, para todo t' pertence a I : t BEFORE t' v t = t' last ( I ) é o elemento t pertence a I tal que, para todo t' pertence a I : t' BEFORE t v t' = t (EDELWEISS, 1998). 2.1.3 Elemento temporal Supondo que exista um conjunto formado por intervalos temporais, a esse conjunto damos o nome de elemento temporal. Ele é uma união finita de intervalos no tempo, que podem ser disjuntos. Um exemplo de elemento temporal é visto na figura abaixo. Ela representa o eixo temporal e alguns intervalos temporais, formando um elemento temporal. ILUSTRAÇÃO 5 - ELEMENTO TEMPORAL Os elementos temporais são conjuntos de intervalos temporais e dessa forma(AMO) são fechados para as operações de união, interseção e complemento da teoria dos conjuntos. Qualquer uma dessas operações sobre elementos 22 temporais produz um outro elemento temporal. Um elemento temporal também é um subconjunto do conjunto de pontos no tempo que formam o eixo temporal, como pode ser visto na figura acima. Em termos de modelagem o elemento temporal é superior ao intervalo temporal, pois facilita a reativação de objetos e simplifica a aplicação do rótulo temporal, pois em determinados casos não há necessidade de fragmentar o objeto em várias tuplas. Tomando como exemplo a tabela 3 percebe-se que, para cada variação da tupla é necessário criar um novo registro que mostre o dado modificado. No caso de uma reativação de cadastro, um elemento temporal pode reduzir a fragmentação. id_funcionario nome_funcionario dataAdmissao_funcionario dataDemissao_funcionario 1 João da Silva 04/01/2005 12/08/2005 1 João da Silva 27/02/2006 agora 2 Janete Cunha 11/02/2006 agora Na tabela acima, existem duas tuplas para o funcionário “João da Silva”, que representam dois períodos em que esteve à serviço de uma determinada organização. A união dos dois períodos de contratação resulta num conjunto que possui dois intervalos temporais. C ={ [04/01/2005, 12/08/2005], [27/02/2006, agora] } O conjunto C dos períodos de contratação é justamente um elemento temporal. Se a tabela for representada utilizando os conceitos de intervalo temporal e elemento temporal tem-se reduzida a fragmentação das tuplas relacionadas ao funcionário “João da Silva” para apenas uma, que contém todos os períodos de contratação. 23 TABELA 4 - TABELA DE FUNCIONÁRIOS COM ELEMENTO TEMPORAL id_funcionario nome_funcionario periodoContratacao_funcionario 1 João da Silva [04/01/2005, 12/08/2005], [27/02/2006, agora] 2 Janete Cunha [11/02/2006, agora] 2.1.4 Duração temporal A duração temporal também é uma primitiva temporal. Ela é fixa ou variável, dependendo do que se quer representar. Um caso em que ela é fixa é a duração de uma hora que é sempre de 60 minutos. Já a duração de um mês pode variar entre 28, 29, 30 e 31 dias. 2.1.5 Fluxo do tempo A dimensão temporal é composta por um conjunto de pontos consecutivos no tempo ao qual denominamos eixo temporal. (EDELWEISS, 1998). O fluxo do do tempo pode, no entanto, ser interpretado de várias maneiras. Quando afirma-se que o tempo flui linearmente significa que há uma total ordenação entre dois pontos quaisquer. Este é o caso mais simples de fluxo temporal. O tempo pode ser ramificado (branching time), no qual cada ponto no tempo tem múltiplos sucessores ou antecessores imediatos. O tempo ramificado no futuro pode denotar múltiplos desenvolvimentos futuros do domínio, representando a realidade de forma bastante fiel. O tempo pode fluir de maneira cíclica, avançando e retornando ao ponto inicial, tal qual os dias da semana, ou as estações do ano. 24 2.1.5.1 TEMPO TOTALMENTE ORDENADO O tempo linearmente ordenado pode ser definido através da teoria dos conjuntos. Seja T o conjunto de todos os pontos no tempo. T é um conjunto totalmente ordenado pela relação before. ∀ ta , tb : ta , tb∈T ∧ta≠tb ta before tb∨tb before ta A relação before possui as seguintes propriedades para que seja uma relação de ordem estrita total: inflexibilidade, transitividade, assimetria. – Inflexibilidade: ∀ t : t∈T ¬t before t – transitividade: ∀ t a , t b , t c : t a , t b , t c ∈T ∧t a ≠t b t a before t b∨t b before t a – assimetria: ∀ t a , t b : t a ,t b ∈T ∧t a before t b ¬t b before t a Ela é equivalente à relação “<“ utilizada nos número inteiros. 2.1.6 Tempo absoluto e tempo relativo O tempo absoluto é específico, definido com uma granulidade determinada e associado a um fato. Por exemplo: João da Silva foi contratado dia 27/08/2006. Neste exemplo tem-se um fato: a contratação de João; tem-se uma granulidade: dia; e, por fim, tem-se um tempo específico. O tempo relativo é válido somente porque outro evento no qual se baseia também é valido. Um exemplo seria o dia das mães. Ele é condicionado ao segundo domingo de maio, ou seja ocorre na data especificada por um evento válido, o segundo domingo do mês de maio. 25 Em bancos de dados temporais pode haver tanto o tempo absoluto, quanto o tempo relativo, sendo que o tempo absoluto é mais comum. O tempo relativo existe no caso de restrições temporais, nas quais a validade de um determinado tempo depende de outro. 2.1.7 Tempo de transação e tempo válido Em bancos de dados temporais podemos definir três conceitos (1) tempo de transação, (2) tempo de validade, (3) tempo definido pelo usuário. O tempo de transação é fornecido pelo SGBD, no momento da inserção ou atualização de algum atributo no banco de dados. Toda entidade presente no banco de dados tem um tempo de transação. Ele representa o tempo em que um fato é válido no banco de dados. Por exemplo, o valor “63” pode ser guardado num banco de dados e ter um tempo de transação associado a ele. Toda vez que esse valor for alterado, ou se um dia for excluído ele deixará de ser válido no banco de dados e o tempo da transação marcará o início e o fim de sua validade no banco. O tempo de validade é o conjunto de instantes em que um fato é verdadeiro na realidade modelada pelo banco de dados. Todo fato tem um tempo de validade por definição, mas nem sempre é preciso armazená-lo por alguns motivos. Por exemplo, ele pode não ser relevante para a aplicação, ou pode não ser conhecido. Ele não pode ser suprido pelo próprio SGBD, mas tem que ser informado pelo usuário. O tempo definido pelo usuário são as informações de tempo dadas explicitamente pelo usuário, ou tratadas pela aplicação. 26 2.1.8 Representação do tempo O tempo pode ser representado de forma explícita em um banco de dados através de um rótulo temporal associado às tuplas. Neste caso todos os valores que foram assumidos por um atributo são armazenados e tratados pelo banco de dados. O tempo é implícito quando tratado através da utilização de uma linguagem de lógica temporal. Utilizando-se formalismos lógicos o tempo é implicitamente armazenado através de operadores temporais. 2.2 CLASSIFICAÇÃO DOS BANCOS DE DADOS TEMPORAIS De acordo com a utilização de tempo de transação ou tempo de validade para essa representação surge essa classificação. Assim, existem algumas categorias de bancos de dados temporais: Instantâneos, de Tempo de Transação, de Tempo de Validade, Bitemporais e Multitemporais. Os bancos de dados Instantâneos correspondem aos bancos de dados convencionais em que não há qualquer mecanismo para tratar os dados temporais de forma implícita. A manipulação de dados temporais é feita de forma explícita através dos programas de aplicação e os dados antigos são sempre sobrepostos por dados novos a cada atualização. Isso significa que serão armazenados somente os dados do presente, ou dados associados a um tempo explicitamente tratado pela aplicação ou usuário. Os bancos de dados de tempo de transação são os que se utilizam do tempo de inserção dos dados no Banco como rótulo temporal. Este tempo de inserção é 27 fornecido pelo próprio SGBD. A alteração do valor de uma propriedade não destrói o valor anteriormente armazenado, mas um novo valor é inserido no banco utilizando o tempo fornecido pelo SGBD. Os bancos de dados de tempo de validade utilizam-se de valores fornecidos pelo usuário e que representam a validade dos dados no mundo real. Segundo Santos os dados antigos não são sobrepostos também (2003, p. 17). Este tipo de banco de dados permite se sejam corrigidas informações do passado - se alguma das informações tiver sido registrada incorretamente, é feita uma nova definição com a data de validade correspondente, sendo que somente a versão atual dos dados é a disponível. (EDELWEISS, 1998. Os bancos de dados bitemporais misturam os dois últimos tipos, armazenando o tempo de validade e o tempo de transação. O estado atual do banco de dados é representado pelos dados atualmente válidos. Nele podemos recuperar todos os aspectos passados dos dados. É possível verificar até os valores que eram considerados válidos, mas que foram corrigidos. Os bancos de dados multitemporais utilizam-se ora do tempo de validade, ora do tempo de transação ou de ambos, fazendo com que ele seja uma mistura dos três últimos tipos vistos anteriormente. 2.3 CONSULTAS A BANCOS DE DADOS TEMPORAIS As linguagens de consultas utilizadas em bancos de dados temporais têm que permitir a recuperação de informações no âmbito temporal ou não, ou seja de todas as informações armazenadas no Banco de dados. Elas permitem: − fornecer valores de propriedades de domínio temporal. Exemplo: a data de nascimento de uma pessoa. 28 − se referir a um determinado instante ou intervalo temporal. Exemplo: Qual o valor do salário no dia 01/01/2006. − recuperar valores com base em restrições temporais. Exemplo: Recuperar todos os valores do salário no dia 01/01/2006. − fornecer informações temporais: Exemplo: Qual a data em que foi alterado o salário de um funcionário. Através da lógica temporal as linguagens de consulta a bancos de dados são enriquecidas para manipular a dimensão temporal e inferir valores não explicitamente armazenados. 2.3.1 Problemas no processamento de consultas temporais Há um grande volume de dados armazenados quando se trata de bancos de dados temporais, uma vez que as informações antigas não são descartadas. Isso torna a indexação mais complicada e pode interferir na velocidade de processamento das consultas. Isso faz com que métodos de indexação alternativos sejam necessários. Outra coisa é a necessidade de manipular informações incompletas. Os tipos de consultas que podem ser realizadas em bancos de dados temporais dependem do tipo de banco de dados. Os bancos de dados instantâneos não dão suporte a consultas temporais. Os bancos de dados de tempo de transação permitem consultas a dados atualizados e dados inseridos anteriormente. O tempo de transação está 29 implicitamente associado aos dados e é ele que identifica os dados requeridos numa consulta. Nos bancos de dados de tempo de validade, podem ser recuperadas informações referentes ao presente, ao passado e previsões para o futuro, dos dados armazenados. Os bancos de dados bitemporais misturam os conceitos dos bancos de dados de tempo de transação e de validade, permitindo consultas tanto ao tempo fornecido pelo SGBD, quanto ao tempo fornecido pelo usuário. O conjunto de todos os dados coligidos neste tipo de bancos de dados representa sua história. É possível portanto recuperar todos os aspectos da informação, presentes, passados e futuros. Os elementos componentes de uma consulta a bancos de dados são um componente de seleção, que representa a entrada dos dados e os parâmetros para a consulta, e um componente de saída (projeção). Em consultas envolvendo dados temporais é utilizada lógica temporal. Os operadores utilizados para tratar de valores temporais são: antes, depois, durante (operadores de comparação), agora, inicio_de_intervalo, distancia_temporal (operadores que retornam valores temporais). As condições podem envolver valores de dados e valores temporais associados aos dados. Existem, portanto, consultas de seleção sobre dados, consultas de seleção temporal e consultas de seleção mista. As consultas de seleção sobre dados não envolvem critérios temporais no componente de seleção. As consultas de seleção temporal envolvem apenas dados temporais no componente de seleção, já as consultas mistas misturam dados e elementos temporais. Analisando o componente de saída verificamos que as saídas podem ser 30 classificadas da mesma forma que as entradas: somente dados, somente informações temporais ou os dois (saída mista). Só não é possível ter saídas temporais quando a entrada também for temporal. 2.4 MODELOS DE DADOS TEMPORAIS Informações temporais estão presentes em um grande número de aplicações do mundo real. Dessa forma, não só as estruturas dos dados manipuladas devem ser definidas, mas também o seu comportamento na passagem do tempo. Nos modelos temporais a variação no tempo é representada através de rótulos temporais associados aos dados. Estes rótulos temporais podem ser de três tipos: − ponto no tempo: um único valor que representa um determinado instante no tempo; − intervalo temporal: um período entre dois instantes no tempo, que pode ser representado utilizando-se dois pontos, um inicial e outro final ao período; − elemento temporal: conjuntos disjuntos de intervalos temporais. Diversos modelos de dados temporais têm sido propostos na literatura, sendo a maioria constituída de extensões temporais aos modelos já existentes. Entre estes, podem ser encontrados modelos relacionais (HRDM [CLI 93], TRM [NAV 93]), entidaderelacionamento (TempER [ANT 97], ERT [LOU 91]). (SANTOS, 2003, p. 17) Nos modelos temporais relacionais, a representação do tempo geralmente é feita através de atributos adicionais, correspondendo ao tempo de transação e/ou tempo de validade. Os modelos de dados temporais Entidade-Relacionamento utilizam entidades, relacionamentos e atributos do modelo padrão (E-R), associando 31 rótulos temporais a estas formas de representação. Os modelos temporais orientados a objetos utilizam as primitivas básicas da orientação a objeto para manipular e armazenar informações. Trabalham com classes, atributos e métodos. A capacidade de recuperar informações é fundamental nos modelos de dados temporais e o tempo pode ser envolvido em consultas de três formas diferentes: para recuperar informações de domínio temporal, para se referir a um instante ou intervalo temporal, ou para recuperar valores com base em restrições temporais. 2.4.1 Modelo temporal TRM O modelo TRM(Temporal Relational Model) é uma modelo no qual temos os aspectos temporais expressos através de um modelo relacional. Ele proporciona uma linguagem de consulta (TSQL) que é capaz de manipular informações estáticas e de caráter temporal de uma forma transparente. Neste modelo, toda relação temporal tem dois atributos obrigatórios: Ts, que é o tempo inicial, e Te, tempo de fim, ou seja, ele é baseado no tempo de validade da informação. O tempo inicial tem que ser sempre preciso para qualquer um dos registros. O tempo de fim nem sempre precisa estar definido. Pode conter o valor null, bem como o valor now (agora), ou um ponto qualquer no tempo. Quando a informação armazenada é a mais atual costuma-se usar Te com o valor now. Já quando é uma informação que será válida no futuro, com o valor null. Um evento instantâneo pode ser representado quanto Ts = Te. Podemos representar, assim, todos os estados de uma informação: passado, 32 presente e futuro. Neste modelo o tempo de validade é parte integrante das relações temporais, sendo que o tempo de transação e o tempo definido pelo usuário podem ser acrescentados através da definição de propriedades temporais, mas isso dependendo da aplicação. 2.4.2 A linguagem de consulta do TRM É a TSQL (Temporal SQL), que acrescenta novas construções sintáticas e semânticas à SQL com a finalidade de permitir consultas em bancos de dados temporais. Ela possui algumas construções adicionais: − cláusula when: esta é similar a cláusula where, mas utilizada para restrição em dados temporais. Alguns operadores de comparação são definidos: before, after, follows, preceds, overlap, equivalent, adjacent. Na utilização dessa cláusula todas as operações são realizadas sobre intervalos. Mesmo tratando-se de pontos isolados no tempo, deve-se convertê-los em intervalos; − recuperação de rótulos temporais: os operadores inter, Time-start e Time-end são utilizados para a expressão de intervalos; − recuperação de informações ordenadas temporalmente: é possível classificar todas as tuplas de uma relação através de rótulos temporais, uma vez que cada uma delas possui uma chave temporal invariante (TIK) e que seus períodos não se sobrepõe; − especificação de domínio de tempo com a cláusula time-slice: limitam a consulta a um determinado período que deve ser identificado através de um 33 indicador específico juntamente com a palavra reservada time-slice; − funções de agregação e cláusula group-by modificadas: a duração de tempo decorrida entre dois instantes é calculada pela função DURATION. Sobre ela podem ser utilizados operadores de agregação (max, min, avg, sum, count). Já a cláusula group by é estendida para sua utilização com rótulos temporais; − especificação de comprimento de um intervalo temporal usando a cláusula moving-window: é a definição de um intervalo de tempo móvel de acordo com a sua duração. Ela pode ser vista como uma função de agregação sobre as tuplas compreendidas no intervalo considerado; 2.5 OPERAÇÕES BÁSICAS SOBRE BANCOS DE DADOS TEMPORAIS Nos bancos de dados temporais as operações de atualização não são realizadas da mesma forma. As informações não podem simplesmente ser substituídas por outras, uma vez que todo o passado dos dados deve ficar armazenado. A exclusão, em um BDT, pode ser de duas formas: exclusão lógica e exclusão física. A exclusão lógica, que norteia o conceito deste tipo de BD, é realizada encerrando-se a “vida” da informação. A exclusão física é realizada quando se deseja remover fisicamente uma informação que não é mais relevante. Esta operação é conhecida por vacuuming e é realizada raramente, somente quando se quer diminuir o número de dados armazenados. (HÜBLER, s. d, p. 2) 34 3 POSTGRESQL O PostgreSQL é um SGBD objeto-relacional, baseado no Postgres versão 4.2 criado no Departamento de Ciência da Computação da Universidade da Califórnia em Berkeley. Ele suporta uma grande parte do padrão SQL:2003 e possui muitas outras funcionalidades, como: ― Chaves estrangeiras; ― Gatilhos; ― Visões; ― Controle de concorrência multi-versão (MVCC); ― Sub-consultas; ― Integridade Referencial; ― Esquemas; Além disso o PostgreSQL pode ser estendido adicionando-se: ― tipos de dados; ― funções; ― operadores; ― funções de agregação; ― métodos de índice; ― linguagens procedurais; O PostgreSQL é um banco de dados relacional que incorpora tecnologias de orientação à objeto, mas de uma maneira diferente dos sistemas gerenciadores de bancos de dados orientados a objetos. Ele obedece ao padrão SQL:1999, cujo modelo de objetos não corresponde ao das linguagens de programação orientadas a objeto. Dessa forma, o termo “orientado a objeto” não pode ser usado para 35 descrever o PostgreSQL Por causa de sua licença, pode ser usado, modificado e distribuído por qualquer pessoa, para qualquer finalidade, sem nenhum ônus. Ele possui a maioria dos recursos presentes em bancos de dados comerciais, como Oracle, Sybase e DB2. 3.1 TIPOS DE DADOS PARA DATA E HORA O PostgreSQL suporta os seguintes tipos de dados para data e hora: TABELA 5 - TIPOS DE DADOS SUPORTADOS PELO POSTGRESQL Nome Timestamp (without time zone) Bytes 8 Descrição Data e hora Menor valor Maior valor 4713 AC 5874897 DC Timestamp (with 8 time zone) Data e hora com 4713 AC fuso-horário 5874897 DC interval 12 Intervalo de tempo -178.000.000 anos 178.000.000 anos Date 4 Data 4713 AC 32767 DC Time (without time zone) 8 Hora 00:00:00.00 23:59:59.99 Time (with time zone) 12 Hora com fusohorário 00:00:00.00+12 23:59:59.99-12 Além disso trabalha com alguns valores especiais para entrada de data e hora. Desses os valores infinity e -infinity possuem representação especial dentro do sistema, não exibindo seus valores, mas apenas os rótulos infinity e -infinity. 36 TABELA 6 - VALORES ESPECIAIS PARA DATA E HORA Rótulo de entrada Tipos correspondentes Descrição epoch Date, timestamp 1970-01-01 00:00:00+00 (hora zero do sistema Unix) infinity timestamp mais tarde que todos os outros carimbos do tempo -infinity timestamp mais cedo que todos os outros carimbos do tempo Now Date, time, timestamp hora de início da transação corrente Today Date, timestamp meia-noite de hoje Tomorrow Date, timestamp meia-noite de amanhã Yesterday Date, timestamp meia-noite de ontem Allballs time 00:00:00.00 UTC Também podem ser utilizadas as seguintes funções, compatíveis com o padrão SQL, para obter o valor corrente de data e hora para o tipo de dado correspondente: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, LOCALTIME e LOCALTIMESTAMP. Internamente o PostgreSQL utiliza datas Julianas para todos os cálculos de data e hora, porque estas possuem a propriedade de calcular corretamente qualquer data mais recente que 4713 AC, partindo da premissa que o ano tem 365,2425 dias. 3.2 O POSTGRESQL E A IMPLEMENTAÇÃO DE ASPECTOS DA TEORIA DE BANCOS DE DADOS TEMPORAIS O PostgreSQL não possui suporte nativo a aspectos temporais, fora o armazenamento de tipos de dados temporais (data, hora e intervalos). Todas as características de um banco de dados temporal teriam que ser implementadas no 37 caso de se desejar suporte nativo do banco. Tempo de transação, tempo de validade, restrições e consultas temporais não são suportados. Existem algumas poucas camadas de software que fazem a emulação de um banco de dados temporal sobre o PostgreSQL Uma vez modelado o banco de dados e armazenadas suas tabelas no PostgreSQL, é possível trabalhar como se o PostgreSQL fosse, de fato, um SGBD temporal. Estes serão descritos a seguir. 3.2.1 Bi-Temporal PostgreSQL O Bi-Temporal PostgreSQL (BtPgSQL) é um módulo, construído usando a linguagem interpretada Ruby, que contém um conjunto de classes usadas para gerenciar relações bitemporais no PostgreSQL Ele é projetado para ser uma camada de abstração entre uma aplicação e o PostgreSQL, permitindo que toda complexidade do gerenciamento de dados temporais seja escondida do programador. Todo código SQL necessário para trabalhar com dados temporais é gerado pelo BtPgSQL. O BtPgSQL requer algumas tabelas específicas para trabalhar corretamente, as quais chama de tabelas de sistema. As chamadas tabelas de usuário são usadas para armazenar os dados especificados na modelagem do banco. As tabelas de sistema guardam quais são as tabelas de usuário, quais campos dessas tabelas são chaves primárias, quais deles são chave estrangeira e quais ações devem ser executadas quando há alteração, ou exclusão de dados, nas quais chaves estrangeiras estão envolvidas. O BtPgSQL possui as seguintes tabelas 38 de sistema: btrel: contém as tabelas temporais existentes no banco de dados; btfield: lista os atributos e sua localização em cada uma das tabelas temporais; btpk: enumera as chaves primárias (se houverem) das tabelas temporais; btfkactions: que ações tomar quando atualizações e exclusões em tabelas com relacionamentos temporais estão envolvidas; btfks: lista das chaves estrangeiras de tabelas temporais com suas ações quanto à exclusão e atualização de valores. Para o BtPgSQL funcionar corretamente a estrutura das tabelas de usuário precisa estar armazenada nas tabelas de sistema e as tabelas de usuário tem que sofrer algumas modificações. É preciso remover as chaves primárias e chaves estrangeiras das tabelas e acrescentar alguns atributos a elas: ― vt_begin timestamp(0) without time zone not null: tempo de início de validade (inclusivo); ― vt_end timestamp(0) without time zone not null: tempo de fim de validade (exclusivo); ― tt_start timestamp(0) without time zone not null: tempo de início de transação (inclusivo); ― tt_stop timestamp(0) without time zone not null: tempo de fim de transação (exclusivo); ― btpk int not null: chave primária bitemporal; ― btid serial unique not null: identificador único para os registros da tabela. Tome-se a tabela abaixo como exemplo: create table cliente ( id_cliente int, 39 nome_cliente text, endereco_cliente text, primary key (id_cliente) ); Retira-se a chave primária da tabela e são acrescentados os atributos requeridos pelo BtPgSQL. create table cliente ( id_cliente int, nome_cliente text, endereco_cliente text, -- atributos requeridos pelo BtPgSQL vt_begin timestamp(0) without time zone vt_end timestamp(0) without time zone tt_start timestamp(0) without time zone tt_stop timestamp(0) without time zone btpk int not null, btid serial unique not null not not not not null, null, null, null, ); Em seguida preenche-se as tabelas de sistema do BtPgSQL com os dados da tabela cliente para que ele possa entender os relacionamentos. -- definindo tabela temporal insert into btrel values ('cliente'); -- definindo campos insert into btfield insert into btfield insert into btfield insert into btfield insert into btfield insert into btfield insert into btfield insert into btfield insert into btfield da tabela values ('cliente','id_cliente', values ('cliente','nome_cliente', values ('cliente','endereco_cliente', values ('cliente','vt_begin', values ('cliente','vt_end', values ('cliente','tt_start', values ('cliente','tt_stop', values ('cliente','btpk', values ('cliente','btid', 0); 1); 2); 3); 4); 5); 6); 7); 8); --define bt tables' pks insert into btpk values ('cliente','id_cliente'); Dos atributos a mais inseridos na tabela, btpk e btid são chaves para a tabela. Btpk é armazena um identificador único para cada um dos registros que 40 compartilham a mesma chave primária, tirando os tempos de validade e de transação. TABELA 7 - TABELA DE CLIENTES BITEMPORAL id_cliente nome_cliente endereco_cliente vt_begin vt_end tt_start tt_stop btpk 1 João da Silva Rua Alpha, 123 12/08/2005 27/06/2006 01/12/2005 30/06/2006 12 1 João da Silva Rua Beta, 789 27/06/2006 infinity 30/06/2006 infinity 12 2 Janete Cunha Rua Gama, 456 11/02/2006 infinity 15/02/2006 infinity 14 O atributo btid simplesmente armazena um identificador único para cada registro da tabela, independentemente de ele fazer, ou não, parte da história do objeto por ele representado. Os passos a serem executados para que o BtPgSQL seja executado sobre uma tabela, como descrito acima, são trabalhosos mas depois de prontos poupam muito trabalho no gerenciamento de dados temporais. Dentre os métodos presentes na classe BtPgSQL, os fundamentais são os que realizam operações sobre os registros do banco de dados: ― seq_insert(*registros) – insere os registros seqüencialmente enquanto verifica se não foi violada nenhuma regra de integridade referencial. Quando os valores de tempo de início de transação e tempo de fim de transação não são especificados, são assumidos os valores -infinity e infinity para cada um deles respectivamente. Tt_start é gravado como now e tt_stop como infinity se não forem explicitados, também. ― seq_delete(inicio_periodo, fim_periodo, registros) – dados um ou mais registros, exclui o intervalo de tempo delimitado por inicio_periodo e fim_periodo dos mesmos, propagando as alterações para os registros que os referenciam. 41 ― seq_update(inicio_periodo, fim_periodo, registros, alterações) – dados um ou mais registros, faz as modificações especificadas em alterações dentro do intervalo de tempo delimitado por inicio_periodo e fim_periodo. O BtPgSQL não faz parte do PostgreSQL, não implementa nada a nível do próprio SGBD, mas fornece uma solução para trabalhar com dados temporais no PostgreSQL, embora, segundo o próprio autor, seja lenta e mais adequada a bases de dados pequenas e médias. Nele pode ser claramente observado o suporte a tempo de transação e tempo de validade de forma explícita. Nesse caso o tempo é tratado como explícito e multidimensional. Há uma preocupação com as restrições de integridade temporal: não são permitidas operações que venham a causar alguma espécie de inconsistência no banco de dados. Um grande ponto fraco é a ausência de construções que simplifiquem a consulta de dados temporais. Torna-se difícil expressar consultas temporais em SQL e não há nenhuma espécie de tratamento para isso. Os métodos que realizam consultas apenas repassam ao PostgreSQL os argumentos neles especificados. 3.2.2 Time travel no PostgreSQL O PostgreSQL nas possuía o time travel, recurso que permitia fazer consultas históricas dos dados armazenados. O mecanismo de armazenamento do PostgreSQL fazia com que os registros armazenados não fossem realmente sobrescritos e nem apagados nas operações de atualização e exclusão. Todo 42 registro recebia dois valores do tipo timestamp chamados xmin e xmax (dois atributos ocultos presentes nas tabelas do PostgreSQL). O atributo xmin recebia um carimbo de data e hora quando da criação do registro ao qual estava associado. O atributo xmax recebia um carimbo quando tal registro fosse marcado como excluído ou alterado. Supondo termos a seguinte tabela no PostgreSQL (apenas para feitos de exemplificação, o timestamp contém somente a data e não, data e hora): TABELA 8 - TABELA DE CLIENTES COM TIMESTAMPS id_cliente nome_cliente endereco_cliente xmin 1 João da Silva Rua Alpha, 123 12/08/2005 1 João da Silva Rua Beta, 789 30/06/2006 2 Janete Cunha Rua Gama, 456 11/02/2006 xmax 30/06/2006 Os registros marcados em cinza representam os dados atuais. Ao ser efetuada uma alteração no registro do cliente “João da Silva”, o registro atual receberia um timestamp no campo xmax, sendo marcado como alterado. Um novo registro seria incluído contendo os dados atualizados do cliente, como visto abaixo. TABELA 9 - TABELA DE CLIENTES COM TIMESTAMPS ALTERADA id_cliente nome_cliente endereco_cliente xmin xmax 1 João da Silva Rua Alpha, 123 12/08/2005 30/06/2006 1 João da Silva Rua Beta, 789 30/06/2006 20/08/2006 1 João da Silva Rua Alpha, 123 20/08/2006 2 Janete Cunha Rua Gama, 456 11/02/2006 Os registros anteriores, cujos valores de xmin e xmax já estariam preenchidos, só eram removidos do banco quando efetuada uma operação chamada vacuum. Se o vacuum não fosse realizado, poderiam ser executadas consultas sobre xmin e xmax para recuperar dados históricos das tabelas a qualquer 43 momento. A utilização do time travel equivale ao armazenamento do tempo de transação. O banco implicitamente armazenaria os valores anteriores preservando a história do banco de dados. Infelizmente isso causava um impacto grande no tamanho das tabelas e a funcionalidade do time travel não está mais presente na versão atual do PostgreSQL Existem um trabalho de A. Elein Mustain que mostra como implementar o time travel utilizando funções armazenadas do próprio PostgreSQL, mas nada nativo do PostgreSQL 44 4 ORACLE O Oracle é um SGBD objeto-relacional líder de mercado, que possui muitos recursos avançados e ferramentas. Possui suporte a transações, gatilhos, procedimentos armazenados, uma linguagem procedural que estende o SQL, o PL/SQL, aceita programação de procedimentos em JAVA, com uma máquina virtual JAVA dentro do banco de dados (chamada Jserver), uso de large objects, que permite armazenar dados como imagens, entre muitos outros recursos. O Oracle pode suportar mais funcionalidades através de extensões ao padrão SQL, como o Oracle Text, para pesquisa em texto; o Oracle Spatial (disponível na versão Enterprise do SGBD) que trabalha com dados geográficos, com dados ligados a coordenadas. Além do que já foi exposto, o Oracle tem suporte nativo a XML. 4.1 TIPOS DE DADOS PARA DATA E HORA Dentre os tipos de dados definidos pelo Oracle temos, obviamente, os tipos de data e hora. O Oracle armazena datas e horas em um formato interno prédefinido. Para entrada desse tipo utiliza o formato DD-MON-YY HH:MI:SS, onde o DD são os dois dígitos do dia, MON são os três caracteres que abreviam o mês, YY, uma representação do ano com dois dígitos, HH são os dois dígitos da hora, MI, dois dígitos dos minutos e SS os dois dígitos dos segundos. O formato de data e hora pode ser modificado através da alteração do valor de constantes como NLS_DATE_FORMAT. 45 O Oracle também suporta operações aritméticas sobre data e hora, nas quais um dia é representado por um inteiro e as horas, minutos e segundos, representados por uma fração. Assim, adicionando-se o valor .5 a uma data é o mesmo que adicionar 12 horas a ela. 12-DEC 99 + 10 = 22-DEC-99 31-DEC-1999:23:59:59 + .25 = 1-JAN-2000:5:59:59 O Oracle 10g tem dois tipos de dados que são intervalos de tempo: interval year to month e interval day to second. 4.1.1 O Oracle e a implementação de aspectos da teoria de bancos de dados temporais 4.1.1.1 WORKSPACE MANAGER Um workspace no Oracle é um mecanismo virtual de compartilhamento de dados entre vários usuários. É como uma porção de dados retirados do banco que pode ser compartilhado para a realização de operações. Um workspace agrupa conjuntos de registros modificados pelos usuários e isola estas versões até que sejam mescladas ao banco de dados de produção. O workspace manager faz com que seja possível atribuir versões a uma ou mais tabelas no banco de dados. Dessa forma, todos os registros em uma tabela podem ter muitas versões diferentes de dados. O mecanismo de versionamento não 46 é visível para o usuário e os comandos SQL continuam a trabalhar como seria esperado, a não ser pelo fato de que uma coluna que contenha uma chave primária não pode ser alterada em um registro que esteja versionado. A opção history faz com que seja possível armazenar todas as mudanças em um determinado registro, adicionando-se um timestamp a ele. Se forem mantidas todas as mudanças (quando a opção history é configurada para “without overwrite”), é possível ter toda a história da tabela armazenada pelo banco de dados. O workspace manager também tem a capacidade de ser utilizado para implementar controle de tempo de validade sobre as tabelas versionadas através de workspaces. Se for habilitado o suporte ao tempo de validade, cada registro terá um atributo a mais para compreender o tempo de validade associado ao registro: WM_VALID. O atributo WM_VALID é do tipo WM_PERIOD, que é um intervalo temporal. Eis a sua definição: CREATE TYPE WM_PERIOD AS OBJECT validFrom validTill ( TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH TIME ZONE ); Na definição do tipo pode-se perceber um tempo de validade inicial: validFrom e um tempo de validade final: validTill. Segue um exemplo da utilização do workspace manager para habilitar suporte ao tempo de validade no Oracle. prático abaixo: Cria uma simples tabela de clientes. CREATE TABLE clientes ( ); nome_cliente VARCHAR2(16) PRIMARY KEY, endereco_cliente VARCHAR(50) 47 Habilita o versionamento na tabela. A opção de de suporte ao tempo de validade é configurada para verdade(true). Isso fará que seja criado um atributo chamado WM_VALID, que armazena o período de tempo de validade, seja criado automaticamente. EXECUTE DBMS_WM.EnableVersioning ('clientes', 'VIEW_WO_OVERWRITE', FALSE, TRUE); Inserindo dados na tabela de clientes: INSERT INTO clientes VALUES( 'João', 'Rua J, 300', WMSYS.WM_PERIOD(TO_DATE('01-01-1990', 'MM-DD-YYYY'), TO_DATE('01-01-2005', 'MM-DD-YYYY')) ); INSERT INTO clientes VALUES( 'Carlos', 'Rua 5, 12', WMSYS.WM_PERIOD(TO_DATE('01-01-2000', 'MM-DD-YYYY'), DBMS_WM.UNTIL_CHANGED) ); INSERT INTO clientes VALUES( 'José', 'Rua J, 100', WMSYS.WM_PERIOD(TO_DATE('01-01-2003', 'MM-DD-YYYY'), TO_DATE('12-31-9999', 'MM-DD-YYYY')) ); COMMIT; Configura o tempo de validade da seção para um intervalo que abrange praticamente todas as datas válidas: EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-1900', 'MM-DD-YYYY'), TO_DATE('01-01-9999', 'MM-DD-YYYY')); Atualiza o endereço de 'José', um cliente cadastrado. Executando uma atualização “seqüencial”, qualquer dado existente sobre José é preservado. Isso resultará em dois registros para José na tabela de clientes. Primeiro é executado um comando para informar o tempo de validade do 48 dado a ser atualizado: EXECUTE DBMS_WM.SetValidTime(TO_DATE('01-01-2003', 'MM-DD-YYYY'), DBMS_WM.UNTIL_CHANGED); Altera o endereço de José: UPDATE clientes SET endereco_cliente = 'Rua K, 157' WHERE nome_cliente = 'José'; Desabilita o o versionamento, mas a coluna com os atributos de tempo de validade permanece na tabela. COMMIT; EXECUTE DBMS_WM.DisableVersioning ('clientes'); A lista de constantes que podem ser utilizadas para a especificação do período de validade WM_PERIOD são: ― DBMS_WM.MIN_TIME: A data mínima suportada pelo workspace manager. Atualmente é o dia 1 de janeiro de 4713 AC. ― DBMS_WM.MAX_TIME: A maior data suportada pelo workspace manager. Corresponde ao fim do dia 31 de dezembro de 9999. ― DBMS_WM.UNTIL_CHANGED: Um valor tratado como DBMS_WM.MAX_TIME até que seja atualizado por modificações no registro. O workspace manager fornece alguns operadores para checagem e operações sobre intervalos de tempo de validade. Os operadores de checagem retornam 1 caso a condição verificada seja verdadeira e 0, se for falsa. Já os operadores que executam ações sobre os intervalos de tempo de validade retornam um intervalo ou null como resultado. Aqui é exibida uma lista com tais operadores que podem ser utilizados em consultas envolvendo tabelas que suportam tempo de validade, sendo que p1 e p2 são intervalos temporais. WM_OVERLAPS( p1, p2 ): Checa se os intervalos p1 e p2 se sobrepõe um ao outro. 49 Por exemplo, tome-se o os intervalos p1(1980, 1990) e p2(1985, 1995). Fazendo WM_OVERLAPS ( p1, p2 ) temos como resultado o valor 1, porque o período de tempo de 1985 a 1990 pertence a ambos os intervalos. Na realidade o que esse operador faz é verificar se a interseção entre os dois intervalos dados como argumentos é vazia, caso não seja retorna o resultado 1, caso seja, retorna 0. WM_CONTAINS( p1, p2 ): Checa se o período p2 está contido em p1. Sendo positiva a checagem, retorna 1, caso contrário, retorna 0. Por exemplo, caso seja executado WM_CONTAINS (p1, p2) sobre os períodos p1(1980,2005) e p2(1990,2000), retornará 1. WM_MEETS( p1, p2 ) : Checa se o período p1 vem antes do período p2 e se os dois são adjacentes. Caso isso seja confirmado, a checagem retorna 1. Tendo p1(1980,1990) e p2 (1990, 2006), o resultado de WM_MEETS(p1, p2) seria 1. WM_EQUALS( p1, p2 ): Checa se o intervalo p1 é igual ao intervalo p2, ou seja, se suas datas inicial e final coincidem. WM_LESSTHAN( p1, p2 ): Checa se o intervalo p1 é anterior, ou seja, ocorre antes do intervalo p2. WM_GREATERTHAN( p1, p2 ): Checa se o intervalo p1 é posterior, ou seja, ocorre depois do intervalo p2. 50 WM_INTERSECTION( p1, p2 ): Retorna a interseção entre os intervalos p1 e p2. Caso não haja interseção retorna null. WM_LDIFF( p1, p2 ): Retorna o intervalo p1 menos o intervalo p2. Exemplos: No caso a seguir, retorna 01/01/1980 a 01/01/1985: WM_LDIFF( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MM-DDYYYY') TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1988', 'MM-DDYYYY') ) O seguinte exemplo retorna null porque p1.validFrom é maior que p2.validFrom: WM_LDIFF( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MMDD-YYYY') TO_DATE('01-01-1975', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DDYYYY') ) Este exemplo retorna p1 pois p2 está totalmente fora do intervalo p1: WM_LDIFF( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MMDD-YYYY') TO_DATE('01-01-1992', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DDYYYY') ) WM_RDIFF( p1, p2 ): Retorna a diferença entre os tempos de fim de validade de dois intervalos p1 e p2. Exemplos: Este exemplo retorna 01/01/1988 a 01/01/1990. WM_RDIFF( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MMDD-YYYY') TO_DATE('01-01-1985', 'MM-DD-YYYY'), TO_DATE('01-01-1988', 'MM-DDYYYY') ) Este exemplo retorna null, porque p1.validTill é menor que p2.validTill. WM_RDIFF( TO_DATE('01-01-1980', 'MM-DD-YYYY'), TO_DATE('01-01-1990', 'MMDD-YYYY') TO_DATE('01-01-1975', 'MM-DD-YYYY'), TO_DATE('01-01-1995', 'MM-DDYYYY') ) Todos esses operadores podem ser utilizados como parâmetros em consultas 51 SQL, que trabalham com tabelas versionadas. Cabem observações quanto às consultas em tabelas versionadas. Todas elas retornarão como resultado os registros cujo intervalo de validades esteja dentro do intervalo definido para a sessão (usando SetValidtime), a menos que o contrário seja especificado nas cláusulas da consulta. Se não houver intervalo de tempo estabelecido para a sessão o resultado será formado com todos os registros da tabela. As atualizações e exclusões também são efetuadas usando o intervalo temporal definido para a sessão. Este será o tempo de validade. Caso não seja especificado o intervalo da sessão, pode ser inserido um intervalo de validade qualquer durante a alteração do registro. Para as inserções pode ser definido um intervalo de tempo de validade qualquer. O workspace manager também trata a integridade referencial das tabelas com tempo de validade. Se houver um relacionamento entre tabelas com tempo de validade será feita a checagem de validade dos registros que se relacionam através de uma chave estrangeira. Caso exista alguma discrepância entre os intervalos de tempo de validade as atualizações, ou exclusões, não são efetuadas. 52 5 ESTUDO DE CASO Como exemplo prático da implementação de um banco de dados temporal em Oracle e no PostgreSQL foi modelado um pequeno banco de folha de pagamento. Nesse banco os requisitos são armazenar os dados do funcionário, como nome e endereço. Os valores de salários também são armazenados na forma de faixas salariais e cada funcionário recebe de acordo com uma dessas faixas de salário. De acordo com a faixa salarial são aplicadas deduções e descontos, gerando assim a folha de pagamento mensal. Deseja-se poder calcular o salário de um funcionário, ou mesmo gerar uma folha de pagamento dado um mês e ano quaisquer. Para que isso seja possível a aplicação pode controlar a inserção e atualização de valores de deduções sobre os salários e de faixas salariais. Seria necessário armazenar e manipular esses valores explicitamente nas tabelas do banco de dados. Utilizando-se, porém, conceitos de bancos de dados temporais e os recursos disponíveis atualmente, pode-se deixar a gerência desses aspectos a encargo do próprio SGBD. Uma observação é que a granulidade exigida neste tipo de aplicação é o mês, uma vez que a folha de pagamento é gerada mês após mês. Resolveu-se para simplificação do modelo não controlar o período de contratação do funcionário e considerar que o mesmo não mude de faixa salarial. Segue abaixo um modelo do banco de dados a ser implementado. 53 Funcionário n 1 Faixa Salarial n n Dedução Como resultado deste pequeno modelo, tem-se as tabelas Funcionario, FaixaSalarial, FaixaSalarial_Deducao e Deducao. As tabelas e seus atributos são especificados a seguir: TABELA 10 - TABELA DE FUNCIONÁRIOS Funcionario ID_funcionario Numérico NomeFuncionario Caractere( 60 ) ID_FaixaSalarial Numérico A tabela acima tem ID_funcionario como chave primária e ID_FaixaSalarial como chave estrangeira que a relaciona com a tabela FaixaSalarial. TABELA 11 - TABELA DE FAIXAS SALARIAIS FaixaSalarial ID_FaixaSalarial Numérico ValorFaixaSalarial Real 54 A tabela acima tem ID_FaixaSalarial como chave primária. TABELA 12 - TABELA DE DEDUÇÕES Deducao ID_Deducao Numérico ValorDeducao Real A tabela acima tem ID_Deducao como chave primária. A seguir a tabela que faz o relacionamento entre valores de dedução e faixas de salário. TABELA 13 - TABELA QUE RELACIONA DEDUÇÕES E FAIXAS SALARIAIS FaixaSalarial_Deducao ID_FaixaSalarial Numérico ID_Deducao Numérico A tabela acima tem ID_FaixaSalarial e ID_Deducao como chaves primárias. ID_FaixaSalarial é chave estrangeira e vem da tabela FaixaSalarial. ID_Deducao também é chave estrangeira e vem da tabela Deducao. 5.1 IMPLEMENTANDO NO ORACLE Após criar as tabelas no Oracle, ativa-se o versionamento para as tabelas de faixas de salário (FaixaSalarial) e de valores de deduções (Deducao). Isso possibilitará, dada uma data qualquer, calcular a folha de pagamento naquele período. A cada uma das tabelas versionadas é acrescentado automaticamente um campo WM_VALID com a data de validade dos dados a ser gerenciado pelo próprio Oracle. EXECUTE DBMS_WM.EnableVersioning ('FaixaSalarial', 'VIEW_WO_OVERWRITE', 55 FALSE, TRUE); EXECUTE DBMS_WM.EnableVersioning ('Deducao', 'VIEW_WO_OVERWRITE', FALSE, TRUE); Antes de inserir ou atualizar qualquer dado nas tabelas versionadas faz-se necessário executar um comando que especifica o tempo de validade dos valores que se deseja inserir ou alterar. Para as consultas faz-se necessário o mesmo procedimento, especificando o tempo abrangido pela consulta. Assim pode-se recuperar dados históricos. 5.2 IMPLEMENTANDO NO POSTGRESQL No PostgreSQL a tarefa de implementar o mesmo modelo seria mais trabalhosa, pois existe a necessidade de se utilizar do BtPgSQL (Bi-Temporal PostgreSQL). Após instalado o PostgreSQL numa máquina Linux, deve ser instalado o interpretador da linguagem Ruby (http://www.ruby-lang.org/). Ainda é preciso instalar um pacote que permite ao Ruby trabalhar com o PostgreSQL (download em http://ruby.scripting.ca/postgres/). Depois disto ainda é necessário instalar o BtPgSQL em si (instruções mais detalhadas podem ser encontradas em http://www.codeforpeople.com/lib/ruby/btpgsql/btpgsql-0.2.4/doc/). Para usar o BtPgSQL as tabelas devem ser criadas sem nenhuma chave, apenas com os campos correspondentes, acrescentado-se os campos requeridos pelo BtPgSQL às tabelas que se deseja acrescentar suporte temporal, no caso FaixaSalarial, Deducao, FaixaSalarial_Deducao. As tabela de Funcionario deve ser 56 criada normalmente: create table FaixaSalarial ( id_faixasalarial int, valorfaixasalarial numeric (10,2), -- atributos requeridos pelo BtPgSQL vt_begin timestamp(0) without time zone vt_end timestamp(0) without time zone tt_start timestamp(0) without time zone tt_stop timestamp(0) without time zone btpk int not null, btid serial unique not null ); not not not not null, null, null, null, not not not not null, null, null, null, not not not not null, null, null, null, create table Deducao ( id_deducao int, valordeducao numeric (10,2), -- atributos requeridos pelo BtPgSQL vt_begin timestamp(0) without time zone vt_end timestamp(0) without time zone tt_start timestamp(0) without time zone tt_stop timestamp(0) without time zone btpk int not null, btid serial unique not null ); create table FaixaSalarial_Deducao ( id_deducao int, id_faixasalarial int, ); -- atributos requeridos pelo BtPgSQL vt_begin timestamp(0) without time zone vt_end timestamp(0) without time zone tt_start timestamp(0) without time zone tt_stop timestamp(0) without time zone btpk int not null, btid serial unique not null Após esse passo devem ser preenchidas as tabelas de configuração do BtPgSQL. Elas é que farão o controle dos relacionamentos e das operações sobre as tabelas do modelo proposto. -- na tabela 'btrel' são inseridos os nomes de todas as tabelas temporais 57 insert into btrel values ('faixasalarial'); insert into btrel values ('deducao'); insert into btrel values ('faixasalarial_deducao'); -- na tabela 'btfield' são inseridos os nomes de atributos insert into btfield values ('faixasalarial', 'id_faixasalarial', 0); insert into btfield values ('faixasalarial', 'valorfaixasalarial', 1); insert into btfield values ('deducao', 'id_deducao', 2); insert into btfield values ('deducao', 'valordeducao', 3); insert into btfield values ('faixasalarial_deducao', 'id_faixasalarial', 4); insert into btfield values ('faixasalarial_deducao', 'id_deducao', 5); -- na tabela 'btpk' é inserida uma lista com as chaves primárias das tabelas temporais insert into btpk values ('faixasalarial', 'id_faixasalarial'); insert into btpk values ('deducao', 'id_deducao'); insert into btpk values ('faixasalarial_deducao', 'id_faixasalarial'); insert into btpk values ('faixasalarial_deducao', 'id_deducao'); -- na tabela 'btpk' é inserida uma lista com as chaves primárias das tabelas temporais insert into btpk values ('faixasalarial', 'id_faixasalarial'); insert into btpk values ('deducao', 'id_deducao'); insert into btpk values ('faixasalarial_deducao', 'id_faixasalarial'); insert into btpk values ('faixasalarial_deducao', 'id_deducao'); -- na tabela 'btfk' fica a lista com as chaves estrangeiras insert into btfk values ('faixasalarial','id_faixasalarial', 'faixasalarial_deducao', 'id_faixasalarial', 0,'cascade','restrict'); insert into btfk values ('deducao','id_deducao', 'faixasalarial_deducao', 'id_deducao', 1,'cascade','restrict'); Após a inserção de toda a estrutura das tabelas no banco de dados as classes do BtPgSQL podem ser utilizadas para fazer inserções, atualizações e exclusões nas tabelas do banco de dados. 58 6 CONSIDERAÇÕES FINAIS Bancos de dados temporais tem sido tema de pesquisa a muitos anos, mas realmente pouca coisa prática tem sido implementada. Nesta pesquisa procurou-se abordar dois SGBDs avaliando o que está sendo implementado por eles da teoria de bancos de dados temporais. Pode-se perceber que o Oracle tem um suporte a tempo de validade gerenciado quase que totalmente pelo banco. O usuário não precisa se preocupar com a criação de campos, apenas com os valores a serem inseridos como tempos válidos. Inclusive os relacionamentos entre tabelas com dados temporais são tratados pelo SGBD. Poderia haver a implementação de uma linguagem de consulta temporal, como o TSQL, mas, em compensação, há funções que estendem as funcionalidades do SQL para suportar as consultas nas tabelas temporais implementadas no workspace manager do Oracle. Já o PostgreSQL não tem suporte nativo a aspectos temporais, limitando-se a tratar tipos de dados como data e horas. É possível implementar suporte semelhante ao do Oracle via gatilhos e funções do PostgreSQL Existem pacotes de software que funcionam como uma camada entre as aplicações e o PostgreSQL que simulam o comportamento de um banco de dados temporal, mas mesmo assim não está completamente definida e padece de problemas de performance. Pode-se perceber que no PostgreSQL o tratamento com dados temporais seria muito mais trabalhoso. Por isso conclui-se que, por enquanto, o Oracle está melhor preparado (não completamente preparado), para trabalhar com dados temporais. Seria interessante que pudesse ser trabalhado o suporte a tempo de transação juntamente com o tempo de validade. Através de gatilhos e procedimentos armazenados, pode-se 59 futuramente desenvolver algo nesse sentido. Como o Oracle é uma ferramenta proprietária, um SGBD comercial, não é possível desenvolver alguma espécie de suporte nativo ao tempo de transação. Já o PostgreSQL é um banco de dados de código aberto e como trabalho futuro pode-se iniciar um projeto para implementação de suporte a tempo de validade e tempo de transação no PostgreSQL Isso abre a possibilidade de estudar a utilização métodos de indexação e armazenamento que trouxessem mais eficiência a um futuro módulo temporal no PostgreSQL Futuramente pode-se trabalhar o suporte a uma linguagem de consulta temporal que facilite a escrita de consultas envolvendo aspectos temporais. 60 REFERÊNCIAS AMO, Sandra A. Introdução aos bancos de dados temporais. Disponível em: <http://deamo.prof.ufu.br/bdtemporal.ps>. Acesso em 22 mar 2006. ANDRADE, Joeva Cristina de. Bancos de dados temporais uma comparação de duas técnicas distintas de desenvolvimento. Disponível em: <http://www.comp.ufla.br/monografias/ano2002/Bancos_de_dados_temporais_uma_ comparacao_de_duas_tecnicas_distintas_de_desenvolvimento.pdfhttp://www.comp. ufla.br/monografias/ano2002/Bancos_de_dados_temporais_uma_comparacao_de_d uas_tecnicas_distintas_de_desenvolvimento.pdf>. Acesso em 21 jun 2006. DATE, C. J. Introdução a sistemas de banco de dados. 8.ed. Rio de Janeiro: Campus, 1990. DOUGLAS, Korry; DOUGLAS, Susan. PostgreSQL: The comprehensive guide to building, programming, and administering PostgreSQL databases. 2. ed. Sams Publishing, 2005. EDELWEISS, Nina. Bancos de dados temporais: teoria e prática. Disponível em <http://www.inf.ufrgs.br/~nina/ArtigosNina/JAI1998.pdf>. Acesso em 12 fev 2006. GREENWALD, Rick; STACKOWIAC, Robert; STERN, Jonathan. Oracle essentials: Oracle database 10g. 3. ed. O'Reilly Media, 2004. HOWARD, Ara. Bi-Temporal PostgreSQL - A PostgreSQL Specific Bi-Temporal Database Emulator. Disponível em <http://www.codeforpeople.com/lib/ruby/btpgsql/btpgsql-0.2.4/doc/> Acesso em 27 ago 2006. HÜBLER, Patrícia nogueira; EDELWEISS, Nina. Definição de um gerenciador para o modelo de dados TF-ORM. Disponível em: <http://www.inf.ufrgs.br/~nina/ArtigosNina/CTDPatricia2001.pdf>. Acesso em 24 nov 2004. JENSEN, Christian S. Introduction to Temporal Database Research. Disponível em <http://www.cs.auc.dk/~csj/Thesis/> Acesso em 13 jun 2006. MURRAY, Chuck. Oracle Database Application Developer's Guide - Workspace Manager. Oracle, 2005. Disponível em <http://downloadeast.oracle.com/docs/cd/B19306_01/appdev.102/b14253/toc.htm> Acesso em 28 ago 2006. MUSTAIN, A. ELEIN. Example of a Timetravel Table. Disponível em <http://www.varlena.com/GeneralBits/122> Acesso em 28 ago 2006. OLIVEIRA, Rosiane Aparecida. Modelagem e desenvolvimento de um banco de 61 dados temporal. Disponível em <http://www.comp.ufla.br/monografias/ano2001/Modelagem_e_desenvolvimento_de _um_banco_de_dados_temporal.pdf> Acesso em 06 ago 2006. SANTOS, Constancia da Silva. Implementação de bancos de dados temporais com versionamento de esquemas: um estudo comparativo. 2003. Dissertação (Mestrado) – UFRGS, Programa de Pós-Graduação em Computação, Porto Alegre, 2003. Disponível em: <http://nina.inf.ufrgs.br/Dissertacao/ConstanciaSantos.pdf>. Acesso em 23 nov 2004. SILVA, Silbene Bueno da. Proposta de modelagem temporal para um banco de dados relacional. Disponível em <http://www.grupobd.inf.ufsc.br/bibliografiaGBD/especializacoes/EspecializacaoSilbeneSilva-ModelagemTemporal-2005> Acesso em 13 jun 2006. THE PostgreSQL GLOBAL DEVELOPMENT GROUP. Documentação do PostgreSQL 8.0.0. Disponível em <http://pgdocptbr.sourceforge.net/pg80/index.html> Acesso em 27 ago 2006.