Encontrei uma solução para duplicar tabelas no DB

Delphi

03/09/2009

Olá amigos,
Como sempre obtenho ajuda em minhas dúvidas, disponibilizo abaixo, função que cria uma nova tabela no DB, com base em outra, identificando inclusive, se a estrutura da tabela destino é diferente da tabela base, incluindo os campos necessários.

Não verifiquei nesse exemplo, campos blob para imagens nem verifiquei se o tamanho do campo é diferente, apenas crio o campo caso ele não exista:

Trata-se de uma função que estou usando e tem se mostrado eficiente para o meu propósito, portanto, podem adequar as suas necessidades.

Utilizo em Fire 1.5

abraço
Mario

Chamada da Função:

ComparaEstruturas(´TABELAORIGEM´,´TABELADESTINO´ );


procedure TfDadosGuarda.ComparaEstruturas(vOrigem, vDestino: string);
var
   TrsAB: Ttransactiondesc;
   vCampoTipo,vCampoTipoD,vOrigemCampo: string;
   vCampoDec,vCampoTam: integer;
   vCampoExiste,vTabelaExiste,vPrimeiraExecucao: boolean;
begin
   lblAndamento.caption := ´Comparando estrutura do arquivo: ´+LowerCase(vOrigem);
   Application.ProcessMessages ;

   // Select Campos de Origem
   dm.cds_aux1.close;
   dm.sql_aux1.commandText := ´SELECT A.RDB$FIELD_NAME CAMPO,´+
                              ´       C.RDB$TYPE_NAME TIPO,´+
                              ´       B.RDB$FIELD_LENGTH TAMANHO,´+
                              ´       B.RDB$FIELD_SCALE DECIMAIS,´+
                              ´       B.RDB$FIELD_PRECISION AS TAMDEC ´+
                              ´FROM   RDB$RELATION_FIELDS A,´+
                              ´       RDB$FIELDS B,´+
                              ´       RDB$TYPES C ´+
                              ´WHERE  (A.RDB$RELATION_NAME = ´´´+vOrigem+´´´) AND ´+
                              ´       (B.RDB$FIELD_NAME = A.RDB$FIELD_SOURCE) AND ´+
                              ´       (C.RDB$TYPE = B.RDB$FIELD_TYPE) AND ´+
                              ´       (C.RDB$FIELD_NAME = ´´RDB$FIELD_TYPE´´) ´+
                              ´ORDER BY RDB$FIELD_POSITION´;
   dm.cds_aux1.open;

   // Select Campos de Destino
   dm.cds_aux2.close;
   dm.sql_aux2.commandText := ´SELECT A.RDB$FIELD_NAME CAMPO,´+
                              ´       C.RDB$TYPE_NAME TIPO,´+
                              ´       B.RDB$FIELD_LENGTH TAMANHO,´+
                              ´       B.RDB$FIELD_SUB_TYPE DECIMAIS ´+
                              ´FROM   RDB$RELATION_FIELDS A,´+
                              ´       RDB$FIELDS B,´+
                              ´       RDB$TYPES C ´+
                              ´WHERE  (A.RDB$RELATION_NAME = ´´´+vDestino+´´´) AND ´+
                              ´       (B.RDB$FIELD_NAME = A.RDB$FIELD_SOURCE) AND ´+
                              ´       (C.RDB$TYPE = B.RDB$FIELD_TYPE) AND ´+
                              ´       (C.RDB$FIELD_NAME = ´´RDB$FIELD_TYPE´´) ´+
                              ´ORDER BY RDB$FIELD_POSITION´;
   dm.cds_aux2.open;
   vTabelaExiste     := (not dm.cds_aux2.Eof);
   vPrimeiraExecucao := True;

   with dm.cds_aux1 do begin
      prog.Max      := RecordCount ;
      while not eof do begin
         prog.Position := RecNo ;
         Application.ProcessMessages ;
         vOrigemCampo := Trim(fieldbyname(´campo´).asstring);
         vCampoExiste := False;
         dm.cds_aux2.first;
         while not dm.cds_aux2.eof do begin
            if Trim(dm.cds_aux2.fieldbyname(´CAMPO´).asstring) = vOrigemCampo then begin
               vCampoExiste := True;
               Break;
            end;
            dm.cds_aux2.next;
         end;
         if not vCampoExiste then begin
            vCampoTipo    := Trim(fieldbyname(´TIPO´).asstring);
            if fieldbyname(´DECIMAIS´).asinteger = 0 then
               vCampoDec  := 0
            else
               vCampoDec  := (fieldbyname(´DECIMAIS´).asinteger*-1);
            vCampoTam     := fieldbyname(´TAMANHO´).asinteger;
            if (vCampoTipo = ´LONG´) AND (vCampoDec = 0) then
               vCampoTipoD := ´INTEGER´
            else if vCampoTipo = ´BLOB´ then
               vCampoTipoD := ´BLOB SUB_TYPE 1´
            else if vCampoTipo = ´VARYING´ then
               vCampoTipoD := ´VARCHAR(´+IntToStr(vCampoTam)+´)  character set WIN1252 collate WIN_PTBR´
            else if vCampoTipo = ´DATE´ then
               vCampoTipoD := ´DDATA´
            else if ((vCampoTipo = ´LONG´) OR (vCampoTipo = ´INT64´)) AND (vCampoDec > 0) then
               vCampoTipoD := ´DECIMAL(´+IntToStr(fieldbyname(´TAMDEC´).asinteger)+´,´+IntToStr(vCampoDec)+´)´;
            try
               TrsAB.TransactionID  := 21;
               TrsAB.IsolationLevel := xilReadCommitted;
               dm.Conexao.StartTransaction(TrsAB);
               if not vTabelaExiste and vPrimeiraExecucao then
                  dm.conexao.ExecuteDirect(´CREATE TABLE ´+vDestino+´ (´+vOrigemCampo+´ ´+vCampoTipoD+´)´)
               else
                  dm.conexao.ExecuteDirect(´ALTER TABLE ´+vDestino+´ ADD ´+vOrigemCampo+´ ´+vCampoTipoD);
               dm.Conexao.Commit(TrsAB);
            except
               dm.Conexao.RollBack(TrsAB);
            end;
            vPrimeiraExecucao := False;
         end;
         next;
      end;
   end;

end;



Aldus

Aldus

Curtidas 0
POSTAR