Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: naderit - Giugno 08, 2016, 02:25:07 pm

Titolo: [RISOLTO]SQLite popolare DB
Inserito da: naderit - Giugno 08, 2016, 02:25:07 pm
Buongiorno a tutti, ho cominciato a lavorare con i database, tentando di migrare un applicazione realizzata in Gambas in Lazarus, riscostruendo il codice da zero.
il mio problema è non riuscire a popolare un database sglite3 prendendo i dati caricati in una StringGrid, Usando l'istruzione For.. To... Do  ottengo la scrittura dell'ultimo record.
allego il codice:

Codice: [Seleziona]
procedure TForm1.Button2Click(Sender: TObject);
var
newFile : Boolean;
i : integer;
K : integer;

begin
  SQLite3Connection1.Close; //Assicurarsi che la connessione viene chiusa quando iniziamo
  SQLite3connection1.DatabaseName:= GetUserDir + Label2.Caption ; // home utente

  try
    //Dal momento che stiamo facendo questo database per la prima volta,
    // verifica del file esistente

    newFile := not FileExists(SQLite3Connection1.DatabaseName);

    if newFile then
    begin
      // viene creato database e talelle
      try
        SQLite3Connection1.Open;

        SQLTransaction1.Active := true;

        // viene creata la tabella

        SQLite3Connection1.ExecuteDirect('CREATE TABLE "pocket"('+
                    ' "idpunto" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
                    ' "Da" VARCHAR(50) NULL,'+
                    ' "A" VARCHAR(50) NULL,'+
                    ' "Lunghezza" REAL DEFAULT NULL,'+
                    ' "Bussola" REAL DAFAULT NULL,'+
                    ' "Inclinazione" REAL DAFAULT NULL);');



        ShowMessage('Data base creato');
      except;
        ShowMessage('Impossibile creare nuovo database');
      end;
    end;
  except;
    ShowMessage('Impossibile controllare esistenza database');
  end;
   sqlquery1.sql.clear;

  for i := 0 to StringGrid1.RowsCount - 1 do;

  begin

  sqlquery1.sql.add(' insert into pocket (Da,A,Lunghezza,Bussola,Inclinazione) values (:Da,:A,:Lunghezza,:Bussola,:Inclinazione)');
     k:=i;
    sqlquery1.params.ParamByName('Da').AsString:= StringGrid1.Cells[0,k];
    sqlquery1.params.ParamByName('A').AsString:= StringGrid1.Cells[1,k];
    sqlquery1.params.ParamByName('Lunghezza').AsString:= StringGrid1.Cells[2,k];
    sqlquery1.params.ParamByName('Bussola').AsString:= StringGrid1.Cells[3,k];
    sqlquery1.params.ParamByName('Inclinazione').AsString:= StringGrid1.Cells[4,k];

  end;
     sqlquery1.ExecSQL;
    SQLTransaction1.Commit;

 end;   


Grazie per l'aiuto
Titolo: Re:SQLite popolare DB
Inserito da: Legolas - Giugno 08, 2016, 03:22:54 pm
Credo che il problema risieda nel fatto che aggiorni la tabella solo alla fine del loop.  Prova ad eseguire i comandi di aggiornamento del database all'interno del loop stesso
Titolo: Re:SQLite popolare DB
Inserito da: naderit - Giugno 08, 2016, 09:35:24 pm
Si avevo già provato ma il risultato non cambia.
in gambas ad ogni ciclo memorizzo il record con update ma in Lazarus non ho trovato una corrispondenza :

Codice: [Seleziona]
rs_poligonale = $conn.Exec("SELECT * FROM pocket") ' query di selezione 

 For i = 0 To GridView1.Rows.Count - 1
    rs_poligonale = $conn.Create("pocket")
  ' rs_poligonale!idpunto è autoincrementale non serve indicizzarlo
 
     k = i
    rs_poligonale!Da = GridView1[k, 0].Text
    rs_poligonale!A = GridView1[k, 1].Text
    rs_poligonale!Lunghezza = GridView1[k, 2].Text
    rs_poligonale!Bussola = GridView1[k, 3].Text
    rs_poligonale!Inclinazione = GridView1[k, 4].Text
   
    rs_poligonale.Update
  Next
Titolo: Re:SQLite popolare DB
Inserito da: Avogadro - Giugno 09, 2016, 05:49:29 am
Perchè non usi zeos lib** ?

Ho provato ad usare lo stesso approccio con le tabelle di Access e ho avuto problemi simili (misteri della sicurezza delle transazioni: "eppure avevo salvato i dati, fatto il commit ...") .

Ho portato i mie dati in sqllite e ho usato zeoslib, che in pratica fa quel che faceva il buon Borland Database Engine (BDE)*, si occupa lui delle transazioni e della loro riusicta.

L' uso di zeos lib appesantisce si il codice pero' almeno si sta tranquilli che i dati vengano scritti e non si perdono da qualche parte nelle linee telematiche


* https://en.wikipedia.org/wiki/Borland_Database_Engine

** http://zeoslib.sourceforge.net/
     http://www.intitec.com/varios/A_ZEOS_basics_tutorial_not_only_for_firebird.pdf
     https://sourceforge.net/projects/zeoslib/


Titolo: Re:SQLite popolare DB
Inserito da: naderit - Giugno 09, 2016, 02:23:11 pm
Bene ho risolto, dopo innumerevoli tentativi  ;D ;D

Codice: [Seleziona]
 for i := 0 to StringGrid1.RowsCount - 1 do begin;

  sqlquery1.sql.text := ' insert into pocket (Da,A,Lunghezza,Bussola,Inclinazione) values (:Da,:A,:Lunghezza,:Bussola,:Inclinazione)';
     k:=i;
    sqlquery1.params.ParamByName('Da').AsString:= StringGrid1.Cells[0,k];
    sqlquery1.params.ParamByName('A').AsString:= StringGrid1.Cells[1,k];
    sqlquery1.params.ParamByName('Lunghezza').AsString:= StringGrid1.Cells[2,k];
    sqlquery1.params.ParamByName('Bussola').AsString:= StringGrid1.Cells[3,k];
    sqlquery1.params.ParamByName('Inclinazione').AsString:= StringGrid1.Cells[4,k];
    sqlquery1.ExecSQL;
  end;

    SQLTransaction1.Commit;

Praticamente l'istruzione "begin" inserita dopo for := ... to...do, vale anche per popolare una semplice listbox, infien al posto di  sqlquery1.sql.add( insert.... , sqlquery1.sql.text:= ' insert.

Spero possa essere utile  ;) ;)
Titolo: Re:[RISOLTO]SQLite popolare DB
Inserito da: Legolas - Giugno 09, 2016, 03:23:09 pm
Ho visto ora due problemini che prima mi erano sfuggiti:
Non so per quale magia ora funzioni, ma ti conviene risolvere adesso o impazzirai nel momento in cui dovessi doverci rimettere mano  ;)
Titolo: Re:[RISOLTO]SQLite popolare DB
Inserito da: naderit - Giugno 10, 2016, 01:35:46 pm
è vero, ho messo un ";" di troppo ...... quanto tempo  ;D ;D
Grazie Legolas
Titolo: Re:[RISOLTO]SQLite popolare DB
Inserito da: Stilgar - Giugno 30, 2016, 12:31:03 pm
Ciao.

Codice: [Seleziona]
for i := 0 to StringGrid1.RowsCount - 1 do begin;

Dopo il begin ; -> funziona perchè begin è inizio blocco e ; è fine istruzione, quindi il parser inserisce un nodo "vuoto" (o così mi aspetterei) e in fase di generazione del codice potrebbe diventare una nop oppure essere ignorato.
Metterlo prima (il punto e virgola) significa scrivere un ciclo for con dentro un nop.
Quindi il blocco sucessivo risulta essere eseguito solo 1 volta.
Legolas spero di aver risposto alla tua domanda implicita. :D

Stilgar