Newsgroup: it.comp.lang.delphi
Titolo: Ancora su importazione dati...

Ho trovato questa procedure in un post su google...Questa procedura copia i
dati da un database all'altro, e copia tutte le tabelle.
Vorrei che non importasse i record uguali (uguali in tutti i campi), ma non
sņ come fare...come al solito sono a digiuno di sql
PS: Nei miei 2 db non ci sono chiavi primarie (non sono
necessarie...credo...č solo un'insermento dati di cavolate...).
Questa č la procedura...se ci capite qualcosa...e come al solito un'immenso
grazie a chi mi risolve o mi aiuta nel problema.
 procedure TForm1.btnImportTablesDataClick(Sender: TObject);
 var
   IndexT, IndexF, IndexR : Integer;
   tsl1, tsl2 : TStrings;
   fsl1, fsl2 : TStrings;
 begin
   if (not ADOConnection1.Connected) or
      (not ADOConnection2.Connected) then
   begin
     ShowMessage('You must select and open the databases first');
     exit;
   end;
   try
     tsl1 := TStringList.Create;
     tsl2 := TStringList.Create;
     fsl1 := TStringList.Create;
     fsl2 := TStringList.Create;
     ADOConnection1.GetTableNames(tsl1, False);
     ADOConnection2.GetTableNames(tsl2, False);
 { For all Tables in Database }
     for indexT := 0 to (tsl1.Count - 1) do
     begin
       Application.ProcessMessages;
       if ADOTable1.Active then ADOTable1.Close;
       if ADOTable2.Active then ADOTable2.Close;
       ADOTable1.TableName := tsl1[IndexT];
       ADOTable1.Open;
       if tsl2.IndexOf(tsl1[IndexT]) > -1 then { Table exist in other
 Database}
       begin
         ADOTable2.TableName := tsl1[IndexT];
         ADOTable2.Open;
         ADOTable1.GetFieldNames(fsl1);
         ADOTable2.GetFieldNames(fsl2);
         ADOTable1.First;
         ADOTable2.First;
 { For all Records in Table }
         for IndexR := 0 to (ADOTable2.RecordCount -1) do
         begin
           ADOTable1.Insert;
 { For all Fields in Table }
           for IndexF := 0 to (fsl1.Count -1) do
           begin
             if fsl2.IndexOf(fsl1[IndexF]) > -1 then { Table exist in other
Database}
             begin
               if ADOTable1.FieldByName(fsl1.Strings[IndexF]).CanModify then
               begin
                 { Copy the data of one field }
                 ADOTable1.FieldByName(fsl1.Strings[IndexF]).Value :=
                 ADOTable2.FieldByName(fsl1.Strings[IndexF]).Value;
               end;
             end;
           end;
           ADOTable1.Post;
           ADOTable2.Next;
           Application.ProcessMessages;
         end;
       end;
     end;
   finally
     ADOTable1.Close;
     tsl1.Free;
     tsl2.Free;
     fsl1.Free;
     fsl2.Free;
   end;
 end;

 end;
comunque questo codice ... come spero adesso avrai
compreso serve a prendere un DB e crearne una esatta
copia su un'altro ma non valuta minimamente se ci sono
delle sovrapposizioni di record ... infatti esegue solo
degli insert sul "nuovo" DB (DB1) ... ora ... quello
che vuoi fare tu ... senza chiavi primarie diventa
molto laborioso e richiede l'uso aggiuntivo di una
Query (parametrica con parametri dinamici a seconda
della tabella) che verifichi l'esistenza di almeno un
record con tutti i campi uguali a quello che vorresti
importare. Almeno questa sarebbe la via più
ottimizzata, che mi viene in mente, per poter
riutilizzare il codice che già hai ... vie un pò più
semplici mi vengono in mente ma produrrebbero un calo
di prestazioni inimmaginabile. Te ne propongo una anche
se io non la userei sinceramente :).
----------------------------------------------------------------
Var
...
  CheckUguale: Boolean;
  i: Integer;
...
Begin
...
   ...
      ...
         ADOTable2.TableName := tsl1[IndexT];
         ADOTable2.Open;
         ADOTable1.GetFieldNames(fsl1);
         ADOTable2.GetFieldNames(fsl2);
         ADOTable1.First;
         ADOTable2.First;
         for IndexR := 0 to (ADOTable2.RecordCount -1) do
         begin
           //Scorre i cercord della tabella del DB1 alla ricerca 
           // di un record ugaule a quello corrente nella tabella del DB2
           For I := 0 To (ADOTable1.RecordCount -1) Do
           Begin
              //Supponiamo che il record sia uguale
              CheckUguale = true;
	 //Scorre tutti i campi della tabella DB1
              for IndexF := 0 to (fsl1.Count-1) do
              begin
                 if fsl2.IndexOf(fsl1[IndexF]) > -1 then
                 begin
                   if ADOTable1.FieldByName(fsl1.Strings[IndexF]).CanModify then
                   begin
                     //verifica l'uguagliaza dei valori
                     If ADOTable1.FieldByName(fsl1.Strings[IndexF]).Value
                        <> ADOTable2.FieldByName(fsl1.Strings[IndexF]).Value Then
                     Begin
                        //Se almeno un campo ha valore diverso nelle due tabelle
                        //Decade l'ipotesi di uguaglianza
                        CheckUguale = false;
                        //possiamo passare al record successivo 
                        //tralasciando gli altri campi
                        Exit For;
                     End;
                   end;
                 end; 
              end;
              //se l'ipotesi di uguaglianza del record è ancora vera
              //tralasciamo gli altri record perchè abbiamo già trovato quello uguale
              If CheckUguale Then
                Exit For;
              //Se no avanza al record successivo 
              ADOTable1.Next;  
           End;
           ADOTable1.First;
           //Se non abbiamo trovato il record uguale 
           //allora passiamo all'inserimento di un nuovo record.
           If Not CheckUguale Then
           Begin
             ADOTable1.Insert;
             for IndexF := 0 to (fsl1.Count -1) do
             begin
               if fsl2.IndexOf(fsl1[IndexF]) > -1 then
               begin
                 if ADOTable1.FieldByName(fsl1.Strings[IndexF]).CanModify then
                 begin
                   ADOTable1.FieldByName(fsl1.Strings[IndexF]).Value :=
                   ADOTable2.FieldByName(fsl1.Strings[IndexF]).Value;
                 end;
               end;
             end;
             ADOTable1.Post;          
           End;  
           ADOTable2.Next;
           Application.ProcessMessages;  
         end;       
      ...
   ... 
...
--------------------------------------------------------------
vista l'ora, il fatto che l'ho scritto di getto e nonin
delhpi e che non l'ho provato, non ti dò nessuna
garanzia su questo codice sia per quanto riguarda la
sintassi che la funzionalità ... la logica credo invece
che stia bene .. spero ... :P
sinceramente non assicuro niente anche sull'ortografia
e la grammatica italiana dell'intero post ... sempre
vista l'ora non rileggerò neanche questo ... speriamo
di non fare troppe brutte figure ... ;P
Fammi sapere ...
Ciao MassimoB
------------------------------------------
http://www.massimobeschi.it/

Ho deciso di creare un campo "quasi univoco". Essendo il db già andato in
giro e già popolato, ho cercato di fare una procedura che mi creasse la
nuova colonna e popolasse la medesima con la concatenazione di alcuni campi.
La creazione della colonna la fà, ma la procedura di creazione delle chiavi
si blocca al centesimo record (un record per niente particolare) e non
capisco il perchè.
Questa è la procedura che ho fatto, se avete idee...
procedure TForm1.BitBtn1Click(Sender: TObject);
var
tsl1: TStrings;
indexT,indexF:integer;
fsl1 : TStrings;
struni:string;
begin
if (not ADOConnection1.Connected) then
 begin
  ShowMessage('You must select and open the databases first');
  exit;
 end;
try
 stato.Lines.Add('Creazione stringlists');
 tsl1 := TStringList.Create;
 fsl1 := TStringList.Create;
 stato.Lines.Add('Retrive delle tabelle');
 ADOConnection1.GetTableNames(tsl1, False);
 stato.Lines.AddStrings(tsl1);
 for indexT := 0 to (tsl1.Count - 1) do
  begin
   if tsl1[indexT]='Generale' then
    begin
     Application.ProcessMessages;
     ADOTable1.TableName := tsl1[IndexT];
     ADOTable1.Open;
     ADOTable1.GetFieldNames(fsl1);
     stato.Lines.AddStrings(fsl1);
     if fsl1.IndexOf('Univoco') = -1 then //non esiste
      begin
       ADOQuery.SQL.Clear;
       ADOCOnnection1.Execute('ALTER TABLE Generale ADD COLUMN Univoco
TEXT(254)'); // creo la colonna se non c'è
       ADOTable1.Close;
       ADOTable1.Open;
       ADOTable1.First;
       for indexF:=1 to (ADOTAble1.RecordCount) do //-1
        begin
         ADOTable1.Next();
// creo il valore stringa che andrà nel nuovo campo (concatenazione dei
campi)
         struni:='';
         if ADOTable1.FieldByName('Frequenza').AsFloat <> 0
           then struni:=struni +
FloatToStr(ADOTable1.FieldByName('Frequenza').AsFloat);
         if ADOTable1.FieldByName('Modulazione').AsString <> ''
            then struni:=struni +
ADOTable1.FieldByName('Modulazione').Value;
         if ADOTable1.FieldByName('Shift').AsFloat <> 0
            then struni:=struni +
FloatToStr(ADOTable1.FieldByName('Shift').AsFloat);
         if ADOTable1.FieldByName('Trasmissioneda').AsString <> ''
            then struni:=struni +
ADOTable1.FieldByName('Trasmissioneda').Value;
         ADOTable1.Edit;
         ADOTable1.FieldByName('Univoco').Value:=struni;
         Application.ProcessMessages;
        end;
      end;
    Application.ProcessMessages;
    end;
  end;
 finally
  ADOTable1.Close;
  end;
end;

Correzione...99° record si incavola e mi restituisce
"Informazioni sulla colonna chiave insufficienti o errate. Troppe righe
interessate dall'aggiornamento."

end;
penso sia questo il problema.
Toglimi una curiosità ma hai a che fare con i
radioamatori? stai facendo un db dei QSO (spero che
siaquesta la sigla ormai non le ricord più)
	Ciao
	MassimoB
 
---------------------------
http://www.massimobeschi.it/

         ADOTable1.Next();
Mettendo qua questo Next ti perdi il primo record su
cui sei.
(correzione effettuata)
se non mi sbaglio manca il post (invio della modifica)
Try
  ADOTable1.Post;
Except
  ShowMessage('Errore sul'+IntToStr(indexF)+'° record con Univoco
="'+struni+'".');
End;
Messo, ma non era quello il problema...l'ho appena risolto... In pratica, se
esistevano già 2 record uguali, non mi permetteva di effettuare la
modifica...ho tolto il record doppio ed ho risolto...ma mi sembra
strano...MOLTO strano...non posso avere record identici?!!?
penso sia questo il problema.
Toglimi una curiosità ma hai a che fare con i
radioamatori? stai facendo un db dei QSO (spero che
siaquesta la sigla ormai non le ricord più)
Si...ma non di QSO...poi ti spiego bene...adesso vado a letto....grazie
infinite! (cmq mi resta il dubbio dei doppi record...se ne avevo già 2
uguali non posso fare l'operazione di creazione "chiave fai da te"...bho!)
Ciao!

Ciao!


Purtroppo non ho definito nessun campo come chiave primaria :\
(Quando creai la tabella me lo propose access, ma mi rifiutai di creare la
chiave).
Mistero...cmq togliendo il record doppio (inutile) funziona tutto :)
Sei stato di grandissimo aiuto, grazie infinite