Desenvolvimento - Visual Basic
Simplifique a Extração de Dados
Utilize um modelo simples de objeto baseado em ODBC para extrair e manipular os dados do SQL Server.
por John CartinProvavelmente, em algum momento, você precisou extrair dados de um banco de dados, no intuito de mover os dados para um outro banco de dados ou criar um backup. Os utilitários para extração vêm junto com cada sistema de gerenciamento de banco de dados relacional (RDBMS - Relational Database Management System), mas eles diferem um do outro e exigem que você utilize diferentes interfaces e metodologias. O que você realmente necessita é de uma ferramenta que extraia os dados de qualquer conexão baseada em ODBC para um banco de dados de formato padrão. Então, você poderá importar estes dados para um outro banco de dados ou arquivá-los para utilização posterior.
Mostraremos como construir uma ferramenta simples de extração de dados baseada no ActiveX Data Objects (ADO) 2.5, que obtém os dados de um banco de dados, tais como SQL Server ou Oracle, e constrói as instruções de inserção SQL dos dados recuperados. Você poderá colocar essas instruções de inserção em outro banco de dados, em qualquer plataforma, ou utilizá-lo como arquivo morto.
Levou algum tempo para que as consultas que eu gravei para a ferramenta funcionassem bem; precisava saber quais campos eram válidos no ambiente de destino e se os valores da chave primária se encaixavam. Para resolver esses problemas, expandi a extração incluindo um modelo de objeto capaz de manipular os dados utilizados na construção das instruções de inserção. O modelo de objeto lhe permite remover certos campos, como por exemplo os campos do tipo Identity, e adicioná-los novamente. Você poderá adicionar novos campos às instruções e salvá-los como arquivos de consulta em lotes (batch) para que possa executá-los mais tarde. Finalmente, você poderá formatar os dados em um banco de dados compatível com os tipos de dados - SQL Server ou Oracle. Esses recursos tornam os dados mais fáceis de serem transportados.
A ferramenta de extração de dados utiliza um recordset ADO para recuperar dados do SQL Server. Se uma instrução SQL está presente, o ADO cria um recordset com o atributo Cursor-Location ajustado para adUseClient. Você terá que criar o recordset desse modo, quando utilizar um disconnected recordset, que significa um recordset sem conexão ativa para a fonte de dados. Se o ADO gerar qualquer sintaxe de erro SQL, após criar o recordset de uma consulta, a ferramenta de extração de dados capta a falha e, por conseguinte, notifica o usuário.
Esse tipo de recordset é muito mais eficiente para se trabalhar num ambiente desktop, porque ele não ocupa os recursos necessários para manter uma conexão ativa com o banco de dados. Ao desconectar o recordset de sua fonte de dados, o atributo RecordCount mantém o valor correto. Se o recordset ainda estiver conectado, o atributo RecordCount terá um valor de -1. Uma vez criado o recordset através da ferramenta de extração, ela abre o recordset assim:
Listagem 1: Abrindo o recordset
m_oRS.Open SQL, m_oConn, adOpenDynamic, adLockOptimistic
Quando o recordset retornar com os dados, a ferramenta de extração armazena-os numa coleção de objetos de registro personalizado, que contém uma coleção de objetos de campo. Esse método de armazenamento de dados é importante, porque você tem dois obstáculos que necessitam de atenção. Primeiro, a ferramenta de extração de dados tem que ser rápida; o desempenho é sempre uma prioridade ao escrever qualquer aplicativo. Segundo, o código tem que expor um fácil acesso programático aos dados para modificar apropriadamente o seu estado. O método de armazenamento de dados encontra um equilíbrio ao adicionar desempenho, sem afetar a eficácia do código ao modificar o estado do objeto.
Formatando os Dados
Uma vez armazenados os dados, inicia-se o verdadeiro trabalho. Para que eles tenham um valor real, você precisará formatá-los em instruções de inserção SQL. Além disso, se você quiser acompanhar as técnicas modernas de orientação a objetos, faz sentido o nível mais baixo de objeto lógico fazer sua própria formatação. Neste caso, o objeto CRecord é o que melhor se encaixa para manipular a formatação, em vez do objeto CField, porque o CRecord tem que lidar com os valores das colunas e dados em cada instrução de inserção. O modelo ADO oferece uma maneira fácil de entender o tipo de dado de cada valor; a enumeração ADODB.DataTypeEnum fornece o método perfeito para se fazer exatamente isso.
Todos os campos em um recordset possuem um atributo Type que associa o tipo de dado do campo ao tipo de dado listado na enumeração ADO DataTypeEnum. Esse atributo pode ser qualquer valor ADO válido, como adInteger, adDate, ou adVarChar (consulte a Tabela 1). A lógica resultante pode suportar a quantidade de tipos de dados que você escolher: mais ou menos. Escolhemos poucos tipos de dados comuns: adInteger, adDate, adVarChar, adVarBinary, adChar e suas variantes associadas.
Tabela 1: Escolhendo um dos tipos de dados ADO. Esses tipos de dados ActiveX Data Objects (ADO) disponíveis foram obtidos através da plataforma Microsoft SDK. Na sua ferramenta de extração, você poderá escolher os tipos de dados que lhe convier.
Constante | Descrição |
adArray | Valor de sinalização associado à outra constante |
adBigInt | Inteiros sinalizados de 8 bytes |
adBinary | Valor binário |
adBoolean | Valor booleano |
adBSTR | Cadeia de caracteres com terminação nula (Unicode) |
adChapter | Valor de módulo de 4 bytes identificando linhas num child rowset |
adChar | Valor de string |
adCurrency | Valor de moeda |
adDate | Valor de data |
adDBDate | Valor de data (yyyymmdd) |
adDBTime | Valor de tempo (hhmmss) |
adDBTimeStamp | Estampa de data/tempo (yyyymmddhhmmss) |
adDecimal | Valor numérico exato com precisão e escala fixas |
adDouble | Ponto flutuante de precisão dupla |
adEmpty | Sem valor |
adError | Código de erro de 32 bits |
adFileTime | Valor de 64 bits representando 100 nanossegundos desde 10 de janeiro de 1601 |
adGUID | Identificador Único Global (Globally Unique Identifier) |
adIDispatch | Ponteiro para uma interface IDispatch de um objeto COM |
adInteger | Inteiros sinalizados de 4 bytes |
adIUnknown | Ponteiro para uma interface IUnknown de um objeto COM |
adLongVarBinary | Valor binário longo |
adLongVarChar | Valor de string longo |
adLongVarWChar | Cadeia de caracteres extensa com terminação nula (Unicode) |
adNumeric | Valor numérico exato com precisão e escala fixas |
adPropVariant | Automação PROP_VARIANT |
adSingle | Ponto flutuante de precisão simples |
adSmallInt | Inteiros sinalizados de 2 bytes |
adTinyInt | Inteiros sinalizados de 1 byte |
adUnsignedBigInt | Inteiros não sinalizados de 8 bytes |
adUnsignedInt | Inteiros não sinalizados de 4 bytes |
adUnsignedSmallInt | Inteiros não sinalizados de 2 bytes |
adUnsignedTinyInt | Inteiros não sinalizados de 1 byte |
adUserDefined | Variável definida pelo usuário |
adVarBinary | Valor binário |
adVarChar | Valor de string |
adVariant | Variante de automação |
adVarNumeric | Valor numérico |
AdVarWChar | Cadeia de caracteres com terminação nula (Unicode) |
adWChar | String de cadeia de caracteres com terminação nula (Unicode) |
Essa ferramenta de extração de dados suporta as regras de sintaxe do SQL Server 7.0, mas oferecendo suporte Oracle, a ferramenta se torna mais útil. Para a maioria dos tipos de dados, SQL Server e Oracle são essencialmente os mesmos; a maior diferença entre os dois é em como eles formatam as datas. A sintaxe do SQL Server para a inserção de datas é simples: o valor da data fica entre aspas simples (‘) . A versão Oracle para o tipo de dado de data depende da função To_DATE() (consulte a seção Fontes de Referência). Você fornecerá suporte para ambos os servidores de banco de dados através de uma variável global no código, baseada no servidor que o usuário direciona. Uma vez conhecendo a plataforma alvo, a função que formata as instruções de inserção escolhe a regra a ser utilizada.
O resultado final da formatação é que a ferramenta de extração de dados recupera as instruções de inserção e adiciona-os à interface do usuário (User Interface - UI). Você realizará essa tarefa através de uma série de loops (um loop dentro do outro). Ao chamar o método GetFormattedData() do objeto CRecord no objeto CConn, você consultará cada objeto CField para cada nome, tipo e valor de campo. Baseado nestes valores, você criará essa instrução de inserção:
Listagem 2: Instrução de inserção
INSERT INTO [TABLE NAME] ([COLUMN LIST]) VALUES ([VALUE LIST])
No objeto CRecord, cada objeto CField retorna seu nome de coluna e valor de campo para ser isolado numa variável privada do objeto CRecord. A função determina o tipo de dado do campo baseado no atributo Type, comparando o campo à enumeração ADO DataTypeEnum. Uma vez determinado o valor do campo, ele será formatado baseado nas regras de sintaxe para o tipo de dado da plataforma do banco de dados escolhida; o valor é formatado apropriadamente (consulte a Listagem 1).
Listagem 3: Essa função de formatação baseada no tipo de dado
Private Function FormatField(FieldName As _ String, FieldType As ADODB.DataTypeEnum, _ FieldValue as Variant) If Len(FieldName) = 0 Then Err.Raise vbObjectError + 2007, , _ "No Field Name was specified for record." Else Select Case FieldType Case ADODB.adChar m_ValueString = m_ValueString & _ """ & FieldValue & "", " Case ADODB.adWChar m_ValueString = m_ValueString & _ """ & FieldValue & "", " Case ADODB.adVarChar m_ValueString = m_ValueString & _ """ & FieldValue & "", " Case ADODB.adVarWChar m_ValueString = m_ValueString & _ """ & FieldValue & "", " Case ADODB.adLongVarWChar m_ValueString = m_ValueString & _ """ & FieldValue & "", " Case ADODB.adDate m_ValueString = m_ValueString & _ """ & FieldValue & "", " Case ADODB.adInteger m_ValueString = m_ValueString & _ """ FieldValue & ", " End Select End If
Assim que a coleção no objeto CRecord consulta cada objeto CField e a função de formatação preenche os buffers privados, sua ferramenta de extração de dados coloca as instruções de inserção juntas e retorna ao objeto CConn. Após a consulta de cada objeto CRecord em seus valores, você escreverá a string resultante na UI, onde poderá ser manipulada ou salva. Após cada objeto CRecord executar um loop através de suas coleções de objetos CField, ele ocupa um buffer contendo as instruções de inserção prontas. Você concatenará e escreverá essas instruções na UI tanto quanto as instruções de inserção SQL separadas pela palavra-chave GO do SQL Server.
Além de salvar as instruções de inserção, a ferramenta de extração de dados também salva o objeto Recordset no formato XML (Extensible Markup Language). O aplicativo realiza a tarefa chamando o método Save() do objeto Recordset e fornece os parâmetros para o caminho do arquivo e PersistFormat - nesse caso, adPersistXML. Você poderá visualizar o código fonte XML em qualquer editor de texto. Por exemplo, o conteúdo da tabela Regions no banco de dados Northwind demonstra a saída XML do recordset.
Quando o usuário clicar no menu Save, a ferramenta de extração de dados exibirá uma caixa de diálogo onde você especificará o caminho e o nome do arquivo. A ferramenta então chamará o método Save do recordset e salvará as instruções de inserção, utilizando o método Save do controle Rich TextBox. Também salvará ambos os arquivos XML do recordset e o arquivo de texto contendo as instruções de inserção, utilizando os mesmos nomes, porém com extensão ORS. Você poderá exportar ambas as instruções de inserção para um banco de dados de destino e o recordset não processado, do qual foi criado.
A ferramenta de extração de dados utiliza arquivos XML para retornar o recordset ao seu estado original e constrói instruções de inserção, como se o recordset fosse construído através de dados reais num banco de dados. Encontrei uma característica pouco comum quando a ferramenta reconstruiu o recordset do arquivo XML: o recordset armazena alguns tipos de dados diferentemente dos outros. Por exemplo, o XML armazena um valor adVarChar como um adVarWChar (uma string de caracteres longos). A plataforma SDK descreve o tipo de dado do adVarWChar como uma cadeia de caracteres com terminação nula Unicode. Você poderá resolver esse problema específico, incluindo o tipo de dado adWVarChar na função de formatação, e a função desempenhará a mesma formatação que é feita para o tipo de dado do adVarChar.
Recuperar o recordset já salvo é simples. Um recordset ADO recupera o seu estado e os dados do arquivo XML; esse arquivo retorna o recordset para o estado exato em que foi salvo. Uma vez feito, a ferramenta o leva através dos mesmos passos que o recordset criado de uma consulta para retornar as instruções de inserção. Quando a ferramenta de extração de dados retorna as instruções de inserção finalizadas, você pode manipular os dados como quiser.
É prático remover campos e adicionar novos. E remover um campo de chave primária de uma consulta poupa tempo, mas a verdadeira mágica de uma ferramenta de extração de dados é a capacidade de adicionar um novo campo de valor em todas as instruções de inserção.
Sobre o Autor
John Cartin mora em Columbia, S.C., é desenvolvedor em tempo integral na VC3 Inc., estudante de Shaolin kung-fu e um médio jogador de futebol.
Download do código referente a este artigo
Clique aqui para fazer o download.- Sou programador, o mágico atende na sala ao ladoPHP
- System Tray - O seu ícone ao lado do relógio do WindowsVisual Basic
- Criando Aplicações Limitadas a Uma Única Instância (Single Instance)C#
- Criando um pacote de instalação com o INNO SETUPVisual Basic
- Nota Fiscal Eletrônica: Construindo um "Servidor de Assinatura Digital" com o NFeExpr...Visual Basic