Fórum Alteração do Banco de Dados Firebird? #59101

11/11/2007

0

Tenho um banco de dados com varias tabelas em meu cliente, onde ele esta continuamente cadastrando ou fazendo alterações, em mh casa, fiz varias modificações nas tabelas, criei novas tabelas, trigger, sp.

Qual é a maneira mais fácil pra eu atualizar esse bancos de dados?

Gerar um script das alterações?

Se for isso. como gerar um script tendo como resultado toda a diferença da estrutura de dois banco de dados?

Tenho que gerar um extract metadata?

Ou seja. mando comparar o banco que está no cliente e o banco que fiz as alterações (acrescentei tabelas, campos em tabalas que já existiam, trigges, etc) e recebo então um script com as linhas necessárias para deixar o banco que está no cliente igual ao banco que fiz as alterações.

O isql, faz isto tambem? Como utiliza-lo?

Sobre o isql ja achei aqui
Citação:
no diretorio do firebird na pasta bin, tem um utilitario isql.exe que permite vc rodar scripts SQL

faz assim:

cria um script sql por exemplo atualiza_cliente.sql com o seguinte conteudo:

ALTER TABLE NOME_DA_TABELA ADD DATA DATE; depois vc pode executar o utilitario passando os parametros isql -i atualiza_cliente.sql -q -user SYSDBA -pass masterkey

e isso ai


Mais gostaria de saber se tem algum programa que faz isso sem ter que usar o isql.


Uso o IBExpert e Firebird 2.0


Adriano_servitec

Adriano_servitec

Responder

Posts

12/11/2007

Gandalf.nho

Você pode montar um utilitário próprio usando um componente como o IBScript, da paleta IBX.


Responder

Gostei + 0

10/12/2007

Aldus

Bom dia Adriano,

eu uso da seguinte forma, criei no meu banco uma tabela que grava quais arquivos sql já usei no sistema, sempre que quero alterar alguma coisa crio um arquivo sql.

Exemplo: SQL00343.SQL
Conteúdo: ALTER TABLE NOME_DA_TABELA ADD DATA DATE

Ao iniciar, verifico os sqls que estão no diretório da aplicação, que se ainda não tiver sido usado, executo-o através da função ExecuteDirect do sqlconnection.

Depois de executado com sucesso, gravo o nome do sql na tabela de atualizações.

Qualquer coisa, posta aí.


Responder

Gostei + 0

08/10/2009

Adriano_servitec

Bom dia Adriano, eu uso da seguinte forma, criei no meu banco uma tabela que grava quais arquivos sql já usei no sistema, sempre que quero alterar alguma coisa crio um arquivo sql. Exemplo: SQL00343.SQL Conteúdo: ALTER TABLE NOME_DA_TABELA ADD DATA DATE Ao iniciar, verifico os sqls que estão no diretório da aplicação, que se ainda não tiver sido usado, executo-o através da função ExecuteDirect do sqlconnection. Depois de executado com sucesso, gravo o nome do sql na tabela de atualizações. Qualquer coisa, posta aí.
Desculpe a demora para responder, mais faz tempo que não mexia mais com programação, porém veio a duvida:

Por exemplo, se eu criar um porjeto e distribuir para varios clientes, depois tenho que aumentar algum campo em alguma tabela, posso fazer usando via SQL assim:
alter table livros add chave char(1);

Correto?

Porém minha duvida é, pensando mais adiante, quando colocar esta nova estrutira da tabela para ser baixado, tem que atualizar nos clientes, então, a melhor forma é criar as tabelas em tempo de projeto no proprio sistema? E toda vez que atualizar algo o sistema recria as tabelas no cliente?


Responder

Gostei + 0

09/10/2009

Aldus

Bom dia,
Não entendi bem sua pergunta, mas eu faço assim:

- Tenho um banco limpo apenas criado que coloco em novos clientes
- Tenho todos os scripts de criação de tabelas e indices em arquivo *.sql
- Quando inicio a aplicação verifico se algum desses arquivos, ou todos no caso de uma nova instalação, já foi usado pelo sistema. Caso não esteja na tabela onde guardo seus nomes, executo o seu conteudo através do .execute. Entao insiro o nome do arquivo na minha tabela de controle e pronto.
- Na proxima execucao, o sistema confrontará novamente a lista de arquivos SQL com a tabela que guardo seus nomes, se não houver nenhum arquivo novo, não executo nada e abro o sistema normalmente..

att


Responder

Gostei + 0

09/10/2009

Facc

[b:ef09d74a95]aldus[/b:ef09d74a95],
Legal esse seu conceito, estou pensando em implementar em meus sistemas.
Mas tenho algumas dúvidas:

[list:ef09d74a95] Como vc faz para comparar o arquivo na pasta com o gravado no banco?[/list:u:ef09d74a95]
[list:ef09d74a95]Não se torna lenta fazendo essa verificação na inicialização?[/list:u:ef09d74a95]
[list:ef09d74a95]E se o usuário, por algum motivo, alterar a pasta onde estão os arquivos *.sql?[/list:u:ef09d74a95]


Responder

Gostei + 0

09/10/2009

Aldus

Segue a função AtualizaBanco que deve ser chamada ao iniciar o sistema:

procedure AtualizaBanco;
var
   TrsAB: Ttransactiondesc;
   SearchRec,SearchDir: TSearchRec;
   ArqSql,ListaArqSql: TStringList ;
   StrSql: string;
   op,QtdArq,RepetirLimpeza: integer;
   ContLoop,vPrimeiroArquivo,AchouVersoes: boolean;
   List: TStrings;
begin
   ListaArqSql  := TStringList.Create;
   AchouVersoes := False;
   List         := TStringList.Create;
   try
      Dm.Conexao.GetTableNames(List);
      for op := 0 to List.Count - 1 do begin
         if LowerCase(List.Strings[op]) = ´versoes´ then
            AchouVersoes := True;
      end;
   finally
      List.Free;
   end;
   if not AchouVersoes then begin
      try
         TrsAB.TransactionID  := 21;
         TrsAB.IsolationLevel := xilReadCommitted;
         dm.Conexao.StartTransaction(TrsAB);
         dm.conexao.ExecuteDirect(´create table versoes (´+
                                     ´arquivosql   varchar(50) not null , ´+
                                     ´data         date , ´+
                                     ´hora         varchar(5) character set WIN1252 collate WIN_PTBR , ´+
                                     ´descricao    varchar(70) character set WIN1252 collate WIN_PTBR , ´+
                                  ´constraint ip_versoes primary key (arquivosql))´);
         dm.Conexao.Commit(TrsAB);
         dm.sql_versoes.CommandText := ´insert into versoes (arquivosql,data,hora) values (:arquivosql,:data,:hora)´;
         dm.sql_versoes.ParamByName(´arquivosql´).AsString := LowerCase(´sc_versoes.sql´);
         dm.sql_versoes.ParamByName(´data´).AsDate         := StrToDate(FormatDateTime(´dd/mm/yyyy´,fMenu.DataSistema));
         dm.sql_versoes.ParamByName(´hora´).AsString       := FormatDateTime(´hh:nn´,Now);
         dm.sql_versoes.ExecSQL;
      except
         dm.Conexao.RollBack(TrsAB);
      end;
   end;

   if (FindFirst(´sql\sc*.sql´, faAnyFile, SearchRec) = 0) then begin
      repeat
         ListaArqSql.Add(SearchRec.Name);
      until
         (FindNext(SearchRec) <> 0);
      FindClose(SearchRec);
      ListaArqSql.Sort ;
      vPrimeiroArquivo     := True;
      for QtdArq:=0 to ListaArqSql.Count-1 do begin
         op:=0;
         dm.cds_versoes.Close ;
         dm.sql_versoes.CommandText := ´select * from versoes where arquivosql=:arquivosql´ ;
         dm.sql_versoes.ParamByName(´arquivosql´).AsString := LowerCase(ListaArqSql[QtdArq]);
         dm.cds_versoes.Open ;
         if dm.cds_versoes.eof then begin
            try
               vPrimeiroArquivo      := False;

               TrsAB.TransactionID   := 22;
               TrsAB.IsolationLevel  := xilReadCommitted;
               dm.Conexao.StartTransaction(TrsAB);

               ArqSql                := TStringList.Create;
               ArqSql.LoadFromFile(´sql\´+ListaArqSql[QtdArq]);

               while op <= ArqSql.Count-1 do begin
                  StrSql   := ´´;
                  ContLoop := True;
                  while ContLoop do begin
                     StrSql := StrSql + Trim(ArqSql.Strings[op]);
                     if ((Right(Trim(ArqSql.Strings[op]),1) = ´;´) or (Trim(ArqSql.Strings[op])=´´)) then
                        ContLoop := False
                     else
                        Inc(op);
                  end;
                  if StrSql <> ´´ then begin
                     for RepetirLimpeza:=1 to 50 do begin
                        StrSql := StringReplace(StrSql,´  ´,´ ´,[rfReplaceAll, rfIgnoreCase]);
                     end;
                     if UpperCase(strSql) <> ´COMMIT WORK;´ then
                        dm.conexao.ExecuteDirect(StrSql);
                  end;
                  Inc(op);
               end;

               ArqSql.Free;
               dm.sql_versoes.CommandText := ´insert into versoes (arquivosql,data,hora) values (:arquivosql,:data,:hora)´;
               dm.sql_versoes.ParamByName(´arquivosql´).AsString := LowerCase(ListaArqSql[QtdArq]);
               dm.sql_versoes.ParamByName(´data´).AsDate         := fMenu.DataSistema;
               dm.sql_versoes.ParamByName(´hora´).AsString       := FormatDateTime(´hh:nn´,Now);
               dm.sql_versoes.ExecSQL;
               dm.Conexao.Commit(TrsAB);
            except
               ArqSql.Free;
               dm.Conexao.RollBack(TrsAB);
               // erro
               break;
            end;
         end;
         Deletefile(´sql\´+ListaArqSql[QtdArq]);
      end;
   end;
end;


Respondendo as suas dúvidas:

* Utilizo uma tabela chamada ´versoes´ para armazenar o nome do SQL incluído e executado.

1) Não se torna lenta fazendo essa verificação na inicialização?
* Note que depois de executar a instrução, eu deleto o SQL do disco


att


Responder

Gostei + 0

09/10/2009

Adriano_servitec

Muito obrigado aldus, respondeu minha pergunta, era esta mesmo a duvida.

Vou adaptar sua função a minha necessidade.

Valeu amigo.


Responder

Gostei + 0

26/11/2012

Anderson Witchs

O right da linha é uma funcao propria sua ou do delphi?
if((Right(Trim(ArqSql.Strings[op]),1) = ;) or (Trim(ArqSql.Strings[op])=)) then

Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar