Esse artigo faz parte da revista Clube Delphi edição 12. Clique aqui para ler todos os artigos desta edição



Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML.

Migrando para Interbase

Migre seu banco de Dados de xBase/Paradox para o Interbase

 

Muitos de nós com certeza tiveram contato ou já utilizaram as bases de dados padrão xBase, usadas em diversas linguagens como o DBase, Clipper, Fox, etc... e também com o Paradox. Aqui apresentaremos algumas dicas para quem está migrando de xBase/Paradox para Client/Server, mais especificamente para o Interbase.

 

I - TIPOS DE DADOS

 

         O Interbase suporta basicamente todos os tipos de dados que o xBase (puro) suporta. Porém, você deve tomar alguns cuidados na conversão de arquivos do xBase para o Interbase quando, por exemplo, os mesmos apresentarem campos numéricos. Utilitários como o DATAPUMP (que acompanha o Delphi) tentam determinar qual o melhor tipo para determinado campo xBase, mas muitas vezes a escolha feita por eles não é compatível com a sua necessidade. Por exemplo, campos numéricos do xBase muitas vezes são convertidos para SMALLINT que facilmente podem ter seus limites ultrapassados. A melhor opção seria utilizar um campo inteiro para campos xBase numéricos (sem casas decimais) e campos NUMERIC (ou DECIMAL) para os campos xBase que contenham casas decimais.

 

Campos do tipo LÓGICO (Boolean/Logical)

 

         O Interbase não tem suporte a esse tipo de dado. Você pode substituí-lo por campos CHAR de 1 caractere (usando por exemplo "T" para true e "F" para false) ou então SMALLINT (utilizando 0 para false e 1 para true). Se você optar pelo uso do tipo CHAR, não defina um COLLATE para esse campo, pois dependendo do collate utilizado, um caractere pode ocupar até 3 bytes, ocupando assim espaço desnecessário.

 

Campos DATA

 

         Até a versão 5.6 do Interbase, os campos do tipo DATE armazenavam data e hora conjuntamente (chamado agora de TIMESTAMP). A partir da versão 6.0 do interbase, utilizando-se o dialeto 3, o tipo DATE armazena somente a data e o  tipo TIME foi criado para armazenar a hora... o novo tipo TIMESTAMP é o equivalente ao DATE das versões anteriores do Interbase e continua armazenando a DATA e HORA em conjunto.

 

Campos Auto-incrementáveis

 

         Esse tipo de campo é muito utilizado em bases de dados PARADOX e pode ser utilizado no Interbase através de técnicas alternativas que simulem um campo AUTOINC, já que o IB não suporta esse tipo de dado nativamente. Inicialmente isso pode parecer uma desvantagem, mas com o tempo você vai ver que não é. A maneira que o programador tem de simular um campo AUTOINC no IB é através da utilização de triggers e generators.

                   Um generator nada mais é do que um contador interno do banco de dados que tem seus incrementos (positivos ou negativos) controlados pelo programador através de instruções SQL utilizadas em triggers, procedures, etc. Os generators não ficam isolados por transações, portanto, se um generator foi incrementando durante uma transação, ele não terá seu valor restaurado caso a transação não se complete (rollback) e todas as outras transações em andamento "enxergarão" o atual valor do mesmo. Basicamente, o que devemos fazer para simular um campo AUTOINC é criar um trigger para o evento BEFORE_INSERT na posição 0, que vai ser disparado antes de um novo registro ser incluído no banco de dados. Nesse trigger devemos checar se o campo "autoinc" contém o valor NULL (ou seja, não tem seu valor especificado). Caso positivo, incrementamos o generator obtendo o seu valor e atribuindo-o ao campo. Caso negativo, deixamos o campo como ele está. Esse método se mostrou, através do tempo, ser a melhor maneira de simular um campo incrementável no IB. Algumas variações dessa técnica podem ser facilmente encontradas em newsgroups ou how-to's disponíveis pela Internet. Segue um exemplo prático da implementação desse método :

Muitos de nós com certeza tiveram contato ou já utilizaram as bases de dados padrão xBase, usadas em diversas linguagens como o DBase, Clipper, Fox, etc... e também com o Paradox. Aqui apresentaremos algumas dicas para quem está migrando de xBase/Paradox para Client/Server, mais especificamente para o Interbase.

 

I - TIPOS DE DADOS

 

         O Interbase suporta basicamente todos os tipos de dados que o xBase (puro) suporta. Porém, você deve tomar alguns cuidados na conversão de arquivos do xBase para o Interbase quando, por exemplo, os mesmos apresentarem campos numéricos. Utilitários como o DATAPUMP (que acompanha o Delphi) tentam determinar qual o melhor tipo para determinado campo xBase, mas muitas vezes a escolha feita por eles não é compatível com a sua necessidade. Por exemplo, campos numéricos do xBase muitas vezes são convertidos para SMALLINT que facilmente podem ter seus limites ultrapassados. A melhor opção seria utilizar um campo inteiro para campos xBase numéricos (sem casas decimais) e campos NUMERIC (ou DECIMAL) para os campos xBase que contenham casas decimais.

 

Campos do tipo LÓGICO (Boolean/Logical)

 

         O Interbase não tem suporte a esse tipo de dado. Você pode substituí-lo por campos CHAR de 1 caractere (usando por exemplo "T" para true e "F" para false) ou então SMALLINT (utilizando 0 para false e 1 para true). Se você optar pelo uso do tipo CHAR, não defina um COLLATE para esse campo, pois dependendo do collate utilizado, um caractere pode ocupar até 3 bytes, ocupando assim espaço desnecessário.

 

Campos DATA

 

         Até a versão 5.6 do Interbase, os campos do tipo DATE armazenavam data e hora conjuntamente (chamado agora de TIMESTAMP). A partir da versão 6.0 do interbase, utilizando-se o dialeto 3, o tipo DATE armazena somente a data e o  tipo TIME foi criado para armazenar a hora... o novo tipo TIMESTAMP é o equivalente ao DATE das versões anteriores do Interbase e continua armazenando a DATA e HORA em conjunto.

 

Campos Auto-incrementáveis

 

         Esse tipo de campo é muito utilizado em bases de dados PARADOX e pode ser utilizado no Interbase através de técnicas alternativas que simulem um campo AUTOINC, já que o IB não suporta esse tipo de dado nativamente. Inicialmente isso pode parecer uma desvantagem, mas com o tempo você vai ver que não é. A maneira que o programador tem de simular um campo AUTOINC no IB é através da utilização de triggers e generators.

                   Um generator nada mais é do que um contador interno do banco de dados que tem seus incrementos (positivos ou negativos) controlados pelo programador através de instruções SQL utilizadas em triggers, procedures, etc. Os generators não ficam isolados por transações, portanto, se um generator foi incrementando durante uma transação, ele não terá seu valor restaurado caso a transação não se complete (rollback) e todas as outras transações em andamento "enxergarão" o atual valor do mesmo. Basicamente, o que devemos fazer para simular um campo AUTOINC é criar um trigger para o evento BEFORE_INSERT na posição 0, que vai ser disparado antes de um novo registro ser incluído no banco de dados. Nesse trigger devemos checar se o campo "autoinc" contém o valor NULL (ou seja, não tem seu valor especificado). Caso positivo, incrementamos o generator obtendo o seu valor e atribuindo-o ao campo. Caso negativo, deixamos o campo como ele está. Esse método se mostrou, através do tempo, ser a melhor maneira de simular um campo incrementável no IB. Algumas variações dessa técnica podem ser facilmente encontradas em newsgroups ou how-to's disponíveis pela Internet. Segue um exemplo prático da implementação desse método :

SNAPSHOT TABLE STABILITY

         Impede que outras transações insiram ou atualizem registros nas tabelas utilizadas por essa transação sem, no entanto, impedir o seu acesso para leitura.

 

READ COMMITTED  

         Permite que a transação enxergue todos os dados que foram "commitados" no BD durante a sua duração, bem como atualizar registros que já foram postados por outras transações sem causar perda de informação. É a transação ideal para um browse.

 

V - TQuery ou TTable ???

 

         Essa foi e continua sendo uma das perguntas mais freqüentes dos programadores em Delphi ou C++ Builder quando começam a utilizar um banco de dados Client/Server.

         Após infinitas discussões a respeito, podemos citar algumas dicas que ajudem você a decidir que tipo de componente utilizar.

         Se a tabela a ser acessada contiver poucos registros e poucos campos, não háverá problema em usar uma Table pois o volume de dados movimentados não será significativo, caso contrário, não pense duas vezes, use uma Query.

         Mas cuidado! A Query também pode ser perigosa dependendo da maneira que foi escrita. Deve-se SEMPRE limitar o volume de dados retornado utilizando-se um condição (WHERE).

         Usuários e programadores xBase estão acostumados a utilizar as famosas telas de BROWSE, onde se pode "passear" livremente por todo o conteúdo de uma tabela.

         Nada impede que você continue utilizando seus browses, mas você vai ter que se acostumar a limitar o número de registros que estão sendo "percorridos". Veja um exemplo prático :

         Você tem uma tabela contendo todos os seus clientes, de diversas cidades e estados brasileiros. O usuário deseja alterar ou consultar a informação de um determinado cliente. Na versão xBase, bastaria simplesmente abrir um BROWSE e talvez utilizar uma função seek para acelerar o acesso ao registro; todos os clientes, de todo o país, estariam sendo listados nesse browse. Se você pensar logicamente, isso é um desperdício de processamento pois o usuário, antes de acessar o browse, já sabe qual o cliente a ser localizado.              Sendo assim, na versão C/S, antes de abrir a Query você pode perguntar ao usuário qual a cidade onde o cliente está localizado e assim setar a cláusula WHERE da Query para retornar apenas os clientes que moram na cidade desejada. Com isso você estaria descartando uma boa parte dos clientes e assim melhorando a performance da rede e o tempo de resposta do seu sistema para o usuário. Existem alguns componentes que permitem que o usuário altere o critério de seleção de uma Query (cláusula WHERE) sem que ele precise conhecer a linguagem SQL. Um exemplo está disponível para download na página http://www.warmboot.com.br/ptg/chcFilter.

         Se você for um programador curioso, utilize o SQL Monitor (que acompanha o Delphi C/S) para monitorar os processos de acesso aos dados feitos por uma Table e você vai ver que todas as operações executadas pela Table são transformadas em código SQL e enviados ao servidor. Sendo assim, você pode imaginar uma Table como a versão "fácil-de-usar" de um Query. O problema é que para garantir todas as regalias que uma Table tem quando acessa uma base de dados xBase (FindKey, FindNearest, etc...), a BDE se utiliza de certos artifícios que na maioria das vezes não são eficientes, fazendo com que as operações fiquem demasiadamente lentas e inoperantes.

         Melhor do que palavras, a experiência vai lhe mostrar quando utilizar uma Table ou uma Query mas, de início, tome por base as informações aqui descritas. Tome cuidado também com os DBGrids, pois eles requerem "fetches" para popular as linhas do Grid e garantir a navegação pelos registros retornados.

         Lembre-se também que você não precisa da BDE para acessar o Interbase. Existem vários componentes alternativos que permitem o acesso ao Interbase e são muito mais eficientes do que a BDE, como por exemplo o Interbase Objects, o FreeIB e o IBX (que acompanha o Delphi 5).

         Para os usuários do Interbase no Brasil, gostaria de lembrar que existe uma lista muito ativa de desenvolvedores onde qualquer um que tenha interesse pode se cadastrar e participar das discussões, bem como enviar suas dúvidas e responder as de outros. A lista pode ser acessada na página da Interbase-BR no endereço http://www.warmboot.com.br/ib ou http://interbasebr.tsx.org .