Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQLite Hilfe zu SUM() ?? (https://www.delphipraxis.net/60516-sqlite-hilfe-zu-sum.html)

Gigant02 8. Jan 2006 11:57

Datenbank: SQLite • Zugriff über: zeoslib

SQLite Hilfe zu SUM() ??
 
moin moin

also ich bastle gerade wieder etwas rum :)

nun habe ich aber ein problem gefunden

ich wollte gerne alle datensätze addieren und dachte mir gut mach das doch einfach mit SUM
SQL-Code:
SELECT satz, SUM(betrag), konten_fk FROM kontoSoll
GROUP BY konten_fk
tja nix da ich habe überall 0 stehen O_o

wie kommt das ?? und wie kann man das am besten lösen ??
ps eine While schleife ist da keine lösung :)

lg, Gigant

mkinzler 8. Jan 2006 12:09

Re: SQLite Hilfe zu SUM() ??
 
Alle nicht nicht Aggregatfelder müssen im GROUP BY sein. d.h. entweder
SQL-Code:
SELECT SUM(betrag), konten_fk FROM kontoSoll
GROUP BY konten_fk
oder
SQL-Code:
SELECT satz, SUM(betrag), konten_fk FROM kontoSoll
GROUP BY satz, konten_fk

Gigant02 8. Jan 2006 12:29

Re: SQLite Hilfe zu SUM() ??
 
ohh das wusste ich noch garnicht

bei mysql geht das doch auch

hmm das war mir super neu

nun gut danke erstmal soweit

//***********************
edit
SQL-Code:
SELECT SUM(betrag), konten_fk FROM kontoSoll
GROUP BY konten_fk
habe das gerade ausprobiert geht aber immer noch nicht !!

bekomme null und das ist ganz falsch

achso das ist kein integer feld liegt es damit zusammen ??
ist ein Float feld

lg, gigant

mkinzler 8. Jan 2006 12:43

Re: SQLite Hilfe zu SUM() ??
 
Zitat:

Zitat von Gigant02
ohh das wusste ich noch garnicht

bei mysql geht das doch auch

Komisch ist eigentlich nicht korrekt
Zitat:


hmm das war mir super neu

nun gut danke erstmal soweit

//***********************
edit
SQL-Code:
SELECT SUM(betrag), konten_fk FROM kontoSoll
GROUP BY konten_fk
habe das gerade ausprobiert geht aber immer noch nicht !!

bekomme null und das ist ganz falsch

achso das ist kein integer feld liegt es damit zusammen ??
ist ein Float feld

lg, gigant
Die Sumfuntion funktionier eigentlich auch bei Floatfeldern.

Gigant02 8. Jan 2006 12:47

Re: SQLite Hilfe zu SUM() ??
 
ja das denke ich mir auch

aber er mag das überhaupt nicht :( er gibt immer eine null wieder

lg, Gigant

mkinzler 8. Jan 2006 12:52

Re: SQLite Hilfe zu SUM() ??
 
Poste mal einen Auschnitt aus deiner Tabelle und die Metadaten.

Gigant02 8. Jan 2006 12:59

Re: SQLite Hilfe zu SUM() ??
 
hmm warte mal fragt sich nur wie ich das am besten mache :(

also da ist nix besonders drin

sie hat 4 felder

Id : integer
Satz : Varchar(40)
betrag : Float
konten_fk : integer

so die sind auch alle brav gefüll

in betrag ist alls in den vormat XX,XX nur zwei nachkomma stellen
also wirklich nix besonderes

lg, Gigant

sir-archimedes 8. Jan 2006 13:02

Re: SQLite Hilfe zu SUM() ??
 
Ist der Betrag wirklich ein Char-Feld? Das wäre nämlich schlecht... Mach daraus mal ein Float/double-Feld. Dann sollte das schon besser gehen :-)

Gigant02 8. Jan 2006 13:07

Re: SQLite Hilfe zu SUM() ??
 
nee wieso siehst du denn Char feld :)

lach nein du ich hatte mich nur vertippt es ist ein Float feld habe aber immer noch den fehler obwohl es ein float feld ist :)

sorry wegen den Tipfehler

sir-archimedes 8. Jan 2006 13:14

Re: SQLite Hilfe zu SUM() ??
 
Also ich kann mir das nicht erklären. Wenn in der Tabelle Daten vorhanden sind, sollte da auch etwas ausgegeben werden.

In der Regel machen auch NULL-Werte in einzelnen Feldern nichts. Die werden entweder zu einer konto_fk-Gruppe NULL zusammen gruppiert oder wenn null in Betrag steckt wird einfach nichts aufaddiert :)

Bist du dir sicher, dass in der Tabelle Daten drin sind? Ist der Betrag immer > 0? Oder kann es sein, dass ich die Beträge alle gegeneinander wegheben? Bzw. inwiefern bekommst du null zurück? 0 Zeilen oder null im Betrag oder 0 im Betrag oder was genau?

mkinzler 8. Jan 2006 13:21

Re: SQLite Hilfe zu SUM() ??
 
Hab mir eine derartige Tabelle erzeugt und die Abfrage funktioniert!
Ist Betrag überall gefüllt ( kein NULL-Wert?)

Gigant02 8. Jan 2006 13:22

Re: SQLite Hilfe zu SUM() ??
 
Liste der Anhänge anzeigen (Anzahl: 1)
hmm also die Datenbank ist gefüllt ganz ganz sicher !!!

und die beträge konnen sich nicht wieder auf null runter summieren da nur plus werte drin sind

hast du schonmal was mit SQLite gemacht

also ich würde gerne die datenbank zur verfühgung stellen damit ihr euch das mal anschauen könnt

die abfrage ist gerade

SQL-Code:
SELECT SUM(betrag), konten_fk FROM kontoSoll
GROUP BY konten_fk
und hier ein Tool um das ganze mal anzusehen

SQLite

mkinzler 8. Jan 2006 13:35

Re: SQLite Hilfe zu SUM() ??
 
Adminprogrogramm funktioniert bei mir nicht. exportiere die Tabelle bitte in csv.

Gigant02 8. Jan 2006 13:37

Re: SQLite Hilfe zu SUM() ??
 
hmm obwohl es steht das das

http://www.orbmu2k.de/indexa.html?ht....php?showid=16

programm das kann habe ich noch nicht rausbekommen wie das programm das kann

welche version hast du von den admin tool herruntergeladen ???

lg, Gigant

Gigant02 8. Jan 2006 13:38

Re: SQLite Hilfe zu SUM() ??
 
hmm nix export

sir-archimedes 8. Jan 2006 13:43

Re: SQLite Hilfe zu SUM() ??
 
Also, ich hab mir das mal runtergeladen und es funktioniert mit deiner ersten SQL-Anweisung problemlos.

Wo führst du das ganze aus? Kann es sein, dass du - falls es bereits in Delphi ist - deine Komponenten (Grid, DataSet, DataSource) einfach nicht richtig verbunden hast? Der SQLite ADministrator machts auf jeden Fall richtig...

mkinzler 8. Jan 2006 13:46

Re: SQLite Hilfe zu SUM() ??
 
Version 0.8: Es Exception, weil er bestimmete Daten nicht findet!

AusBeschreibung des Programmes
Zitat:

ebenso können Daten importiert und exportiert werden.
Jetzt hat es geklappt. :-)

Man kann nur Daten aus einem Query exportieren :-(

Gigant02 8. Jan 2006 13:46

Re: SQLite Hilfe zu SUM() ??
 
lach ja das könnte ich mir ja auch erklärren aber das dumme ist

ich habe es nicht in Delphi sondern es geht schon nicht in denn tool

hmm tolle sache warte mal eben ich lade mir davon die neue version runter und schau mir das dann mal an

lg, Gigant

Gigant02 8. Jan 2006 13:50

Re: SQLite Hilfe zu SUM() ??
 
ES geht :)

lag einfach an den Tool :(

na toll war also nur falscher alarm :(

danke soweit das ihr es mit mir ausgehalten habt

schönen sontag noch :)

lg, Gigant

Gigant02 8. Jan 2006 14:54

Re: SQLite Hilfe zu SUM() ??
 
Tolle Wurst

also ich habe jetzt alles soweit fertig in delphi eingebaut und dachte mir super wird schon laufen

lach nix da sum macht da den gleichen blödsinn also dachte ich mir tauscht die SQLite.dll aus gesagt getan aber wie ich sehe heißt sie jetzt SQLite3.dll und damit kann mein ZeosLib nicht um also muss ich wohl Zoeslib neue version installieren ohje mit der komponente stehe ich ja schon seit langen auf dem kriegsfuss

oder gibt es noch eine andere möglichkeit ?? kann ich mir nicht einfach die änderen der beiden dells ansehen und das so zusammen basteln wie ich das will ???

oder siehst es wohl eher schlecht für mich aus ???

lg, Gigant

mkinzler 8. Jan 2006 15:00

Re: SQLite Hilfe zu SUM() ??
 
Zitat:

Zitat von Gigant02
lach nix da sum macht da den gleichen blödsinn also dachte ich mir tauscht die SQLite.dll aus gesagt getan aber wie ich sehe heißt sie jetzt SQLite3.dll und damit kann mein ZeosLib nicht um also muss ich wohl Zoeslib neue version installieren ohje mit der komponente stehe ich ja schon seit langen auf dem kriegsfuss

Eine neue Version zu installieren ist doch kein Problem ( wenn du nicht von 5 aug 6 wechselst). Normalerweise genügt es die neue über die alte zu installiern!
Zitat:

oder gibt es noch eine andere möglichkeit ?? kann ich mir nicht einfach die änderen der beiden dells ansehen und das so zusammen basteln wie ich das will ???

oder siehst es wohl eher schlecht für mich aus ???

lg, Gigant
???

Vielleicht die sqllit3.dll in SQLite.dll umbenennen ? Ich würe aber die neue zeoslib verwenden.

Orbmu2k 8. Jan 2006 21:49

Re: SQLite Hilfe zu SUM() ??
 
Zitat:

Zitat von mkinzler
Vielleicht die sqllit3.dll in SQLite.dll umbenennen ?

Auf keinen Fall! Sqlite3.dll ist nur für sqlite3 datenbanken gedacht und wird nur in der aktuell im CVS liegenden Version von ZEOS (Mit SQLite3 Support)verwendet.

Zitat:

Zitat von mkinzler
Eine neue Version zu installieren ist doch kein Problem ( wenn du nicht von 5 aug 6 wechselst). Normalerweise genügt es die neue über die alte zu installiern!

Also das hat mir immer nur Ärger eingehandelt, Also am besten ist es die Packages erst zu deinstallieren und danach auch die BPL's zu löschen und dann erst die neue Version einzuspielen.

Zitat:

Zitat von mkinzler
Man kann nur Daten aus einem Query exportieren

Ist aber eineindeutig mit "SQL Ergebnis exportieren" bezeichnet ;-) Mal sehen vieleicht erweitere ich es noch für die Datenansicht.

//EDIT:

@Gigant02

Versuch mal das in deinem Programm:

SQL-Code:
SELECT SUM(betrag) || '', konten_fk FROM kontoSoll
GROUP BY konten_fk

Gigant02 9. Jan 2006 16:21

Re: SQLite Hilfe zu SUM() ??
 
@Orbmu2k

hmm schade schade nee ist nicht geht so auch nicht werd mal eben lach leicht gesagt die neue version von ZeosLib installieren :)

wollte eigentlich nicht auf Version 3 (SQLite) umsteigen weil er die alte datenbank dann nicht mehr öffnen kann oder sehe ich das falsch ???

lg, Gigant

Gigant02 9. Jan 2006 16:45

Re: SQLite Hilfe zu SUM() ??
 
Jup ich habe es mal wieder geschaft

hier geht nix mehr ich drehe gleich druch boar immer habe ich probleme mit dieser alten blöden komponente !!!!

dabei laufen die ja so gut aber das blöde installieren ich habe es genauso gemacht wie beschrieben aber es geht nix

ich habe alle such pfade gesetzt und alles so gemacht wie beschrieben er nörgeld aber rum das er nix findet herlich

und ich habe das problem an zwei rechnern

das bedeutet für mich wieder zwei tage dauer schlechte laune bis das läuft
ich bin einfach zu blöd um die dinger zuinstallieren

lg, Gigant

Gigant02 9. Jan 2006 16:56

Re: SQLite Hilfe zu SUM() ??
 
was uach richtig toll ist

mir fehlen
ZCore.bpl
ZParseSql.bpl
ZPlain.bpl
ZDbc.bpl

toll oder

und kann mal einer so lieb sein und mir einfach mal ein link posten zum richtigen archive ???

ich habe das hier genommen
http://prdownloads.sourceforge.net/z...5.zip?download

ist doch richtig oder ???

//************************************************** *

also ich bin jetzt so vorgegangen
ZeosDBO installations Anleitung

-1- Entpacke das Archive in einen Ordner.
-2- Kopiere Die erforderlichen DLL’S von dem Lib Ordner zu den Windows System Ordner
-3- Füge das Build Verzeichnis des entsprechenden Paketes hinzu.
-4- Öffne das Paketverzeichnis und öffne die ZeosDBO.bpg Projektgruppe und Compoliere die folgenden Componenten in der Listen reihenfolge

- Zcore.bpl
- ZparseSql.bpl
- Zplain.bpl
- ZDbc.bpl

-5- Hast du alle Componenten installiert kommt noch zur guter letzt die Zcomponent.bpl

und er nürgelt immer rum das er einige nicht finden kann ???
und dazu habe ich die

- Zcore.bpl
- ZparseSql.bpl
- Zplain.bpl
- ZDbc.bpl

überhaupt nicht !!!!!

ich bin echt fertig mit meinen nerven bitte hilft mir
lg, Gigant

mkinzler 9. Jan 2006 19:54

Re: SQLite Hilfe zu SUM() ??
 
Es scheint so, das der Ausgabepfad für die bpl-dateien in den Delphiprojekten (dpk's) nicht im Bibliothekspfad der IDE liegt. Enweder diesen Pfad in der IDE übernehmen, die bpl ind anderen Pfad kopieren.

Orbmu2k 9. Jan 2006 20:10

Re: SQLite Hilfe zu SUM() ??
 
Zitat:

Zitat von Gigant02
@Orbmu2k

hmm schade schade nee ist nicht geht so auch nicht werd mal eben lach leicht gesagt die neue version von ZeosLib installieren :)

wollte eigentlich nicht auf Version 3 (SQLite) umsteigen weil er die alte datenbank dann nicht mehr öffnen kann oder sehe ich das falsch ???

lg, Gigant

Das ist richtig du kannst mit SQLite3 keine 2.8er DB Files öffnen ... aber wer sagt das du auf 3 umsteigen musst ? Die neue ZEOS unterstützt es nur ;-) d.h. du kannst mit der sqlite.dll normale sqlite2.8 Files öffnen (Alles wie immer) oder mit der sqlite3.dll die sqlite3 DB Files.

Lass dich von Sqlite und meinem Tool nicht reinlegen! Der Grid in meinem Tool zeigt auch eine MEMO Vorschau an und mit dem ||'' bringst du ihn dazu es wie ein MEMO zu verstehen. Dass da immer ne 0 drin steht heisst das er den DatenfeldTyp falsch zuordnet ... SQLite2.8 kennt im Hintergrund eh nur Strings.


Zitat:

Zitat von Gigant02
und kann mal einer so lieb sein und mir einfach mal ein link posten zum richtigen archive ???
ich habe das hier genommen
http://prdownloads.sourceforge.net/z...5.zip?download
ist doch richtig oder ???

Also die fertigen Builds solllten eigentlich gehen ... Ich verwende aber die CVS Version ... diese dort hat noch kein SQLite3 Support.

Gigant02 10. Jan 2006 17:03

Re: SQLite Hilfe zu SUM() ??
 
hmm das ist doch die CSV version

ich hatte vorher die nicht CSV drauf
also die zeosdbo-6.5.1-alpha

hmm habe die alte soweit wieder zum laufen bekommen (endlich)

hmm was mir aber sagt das ich die alte nicht richtig deinstalliert habe (zum glück)

frage eins

wie deinstalliere ich komonenten ???

Frage zwei
wo ist der unterschied zwischen csv und nicht csv und wo bekomme ich die csv wenn das die nicht csv war ???

frage drei

wenn ich schon die neueste version habe warum kann ich denn bitte nicht mir SUM() arbeiten ??? ich habe nix falsch verlink und auch sonst ist mir kein fehler bekannt :(

also
SQL-Code:
SELECT SUM(betrag) || '', konten_fk FROM kontoSoll
GROUP BY konten_fk
das geht sehr sehr gut in deinen tool (in älteren versionen auch)
aber bei mir gibt es einen SQL fehler aus :(

Delphi-Quellcode:
procedure TfrmEinstellung.Button1Click(Sender: TObject);
var qKonten : tzQuery;
    cSQL   : String;
begin

  cSQL := 'SELECT SUM(betrag) as betrag, konten_fk FROM kontoSoll ' +
          'GROUP BY konten_fk';

  if (DB_Open(qKonten,cSQL)) then begin
    qKonten.First;
    While (Not qKonten.Eof) do begin

      cSQL := 'UPDATE konten SET kontostand = '+qKonten.FieldByName('betrag').asString
             +' WHERE konto_pk = '+qKonten.FieldByName('konten_fk').asString;

      DB_Exec(cSQL);

      ShowMessage(qKonten.FieldByName('betrag').asString);
      qKonten.Next;

    end;
  end;
  qKonten.Free;
end;
so eine kleine erklärrung
DB_OPEN öffnet mir einfach eine Query und DB_Exec ist nur für ausführungen da

das Showmessage gibt mir immer nur 0 zurück :( also einen fehler oder ??

wenn ich da dein code benutze geht das garnicht

lg, Gigant

mkinzler 10. Jan 2006 22:12

Re: SQLite Hilfe zu SUM() ??
 
Zitat:

Zitat von Gigant02
hmm habe die alte soweit wieder zum laufen bekommen (endlich)

frage eins

wie deinstalliere ich komonenten ???

Komponenetn->Packages installieren -> Enfernen.
Pfade aus Umgebungsoptionen/Bibliothekspfad und Suchpfad enfernen.
Verzeichnis löschen.
Zitat:

Frage zwei
wo ist der unterschied zwischen csv und nicht csv und wo bekomme ich die csv wenn das die nicht csv war ???
Unter schied zwischen cvs (nicht csv) und der Nicht-CVS Version ist, das die Entwicklerversion im Versionierungssystem von SF.net neuer ist und neu Features enthält ( z.B. für sqlite3 und FireBird 2.0).
Sie besitzt aber möglicherweise mehr Bugs.
Auf das CVS kann man z.B. mit WinCVS zugreifen.
Zitat:


Delphi-Quellcode:
procedure TfrmEinstellung.Button1Click(Sender: TObject);
var qKonten : tzQuery;
    cSQL   : String;
begin

  cSQL := 'SELECT SUM(betrag) as betrag, konten_fk FROM kontoSoll ' +
          'GROUP BY konten_fk';

  if (DB_Open(qKonten,cSQL)) then begin
    qKonten.First;
    While (Not qKonten.Eof) do begin

      cSQL := 'UPDATE konten SET kontostand = '+qKonten.FieldByName('betrag').asString
             +' WHERE konto_pk = '+qKonten.FieldByName('konten_fk').asString;

      DB_Exec(cSQL);

      ShowMessage(qKonten.FieldByName('betrag').asString);
      qKonten.Next;

    end;
  end;
  qKonten.Free;
end;
so eine kleine erklärrung
DB_OPEN öffnet mir einfach eine Query und DB_Exec ist nur für ausführungen da

das Showmessage gibt mir immer nur 0 zurück :( also einen fehler oder ??
Hast Du in der Prozedur DB_Exec eine loakle TZQuery-Komponente, oder nimmst du die qKonten?
Wie sind die weiteren Einstellungen?
Möglicherweise verschiebt das Update den Zeiger der Abfrage.

Orbmu2k 11. Jan 2006 08:20

Re: SQLite Hilfe zu SUM() ??
 
@Gigant

versuch mal das:
Delphi-Quellcode:
procedure TfrmEinstellung.Button1Click(Sender: TObject);
var qKonten : tzQuery;
    cSQL   : String;
begin

  cSQL := 'SELECT SUM(betrag)||'''' as betrag, konten_fk FROM kontoSoll GROUP BY konten_fk';

  if (DB_Open(qKonten,cSQL)) then begin
    qKonten.First;
    While (Not qKonten.Eof) do begin

      cSQL := 'UPDATE konten SET kontostand = '+ QuotedStr(qKonten.FieldByName('betrag').asString)
             +' WHERE konto_pk = '+qKonten.FieldByName('konten_fk').asString;

      DB_Exec(cSQL);

      ShowMessage(qKonten.FieldByName('betrag').asString);
      qKonten.Next;

    end;
  end;
  qKonten.Free;
end;
Bei SQLite 3 könnte man sowas dann sogar mit einer Query erledigen ;-)

SQL-Code:
update Konten

set KontoStand =
  (select SumBetrag
   from (select
           Sum(ks.betrag) as SumBetrag,
           ks.Konten_FK as KontenFK
         from KontoSoll ks
         group by ks.Konten_FK
        )
   where KontenFK = Konto_PK
  )

delphilevi 11. Jan 2006 09:07

Re: SQLite Hilfe zu SUM() ??
 
versuche doch mal das interface von Ben Hochstrasser
funzt mit den alten sqlite-versionen wunderbar.

du kannst deine query auch direkt über sqlite absetzen und ausschliessen,
daß sql-Syntax-Fehler die Ursache sind. (sqlite.exe runterladen und starten es oeffnet sich
ein dos-fenster Tabellen anlegen ein paar werte einfuegen abfrage absetzen und fertig)


Delphi-Quellcode:
unit SQLite;
{
simple class interface for SQLite. Hacked in by Ben Hochstrasser (bhoc@surfeu.ch)
Thanks to Roger Reghin (RReghin@scelectric.ca) for his idea to ValueList.

use it like this:

procedure TForm1.OnSQLBusy(Sender: TObject; ObjectName: String; BusyCount: integer; var Cancel: Boolean);
procedure TForm1.OnSQLData(Sender: TObject; Columns: Integer; ColumnNames, ColumnValues: String);
procedure TForm1.OnSQLComplete(Sender: TObject);

procedure TForm1.Button1Click(Sender: TObject);
var
  MySQL: TSQLite;
  SQL: String;
begin
  MySQL := TSQLite.Create('test.db');
  MySQL.OnData := OnSQLData;
  MySQL.BusyTimeout := 1000;
  MySQL.OnBusy := OnSQLBusy;
  MySQL.OnQueryComplete := OnSQLComplete;
  SQL := 'CREATE TABLE Test(Name varchar(32), Vorname varchar(32));';
  MySQL.Query(sql, nil);
  SQL := 'INSERT INTO Test VALUES(''Hochstrasser'', ''Benedikt'');';
  if MySQL.IsComplete(sql) then
    MySQL.Query(sql, nil);
  SQL := 'SELECT * FROM Test;';
  MySQL.Query(sql, ListBox1.Items);
  MySQL.DatabaseDetails(Memo1.Lines);
  SQL := 'DROP TABLE Test;';
  MySQL.Query(sql, nil);
  MySQL.Free;
end;

You may also add this to your form if you would like to see the results in a ListView

Procedure TStringsToListView(LstIn: TStrings; LstOut: TListView);
var
  n: integer;
  lTmp: TStringList;
begin
  lTmp := TStringList.Create;
  lTmp.CommaText := LstIn.Strings[0];
  LstOut.Items.Clear;
  LstOut.Columns.Clear;
  for n := 0 to lTmp.Count - 1 do
    with LstOut.Columns.Add do
    begin
      Caption := lTmp.Strings[n];
      AutoSize := True;
      Width := -1;
    end;
  for n := 1 to LstIn.Count - 1 do
  begin
    lTmp.CommaText := LstIn.Strings[n];
    with LstOut.Items.Add do
    begin
      Caption := lTmp.Strings[0];
      lTmp.Delete(0);
      SubItems.Text := lTmp.Text;
    end;
  end;
  lTmp.Free;
end;

There is a similar function for a StringGrid:

Procedure TStringsToStringGrid(LstIn: TStrings; LstOut: TStringGrid);
var
  n: integer;
  i: integer;
  lTmp: TStringList;
begin
  if (LstIn <> nil) and (LstOut <> nil) then
  begin
    lTmp := TStringList.Create;
    lTmp.CommaText := LstIn.Strings[0];
    lstOut.ColCount := Ltmp.Count;
    lstout.RowCount := 1;
    lstout.FixedCols := 1;
    lstout.Rows[0] := ltmp;
    i := 1;
    for n := 1 to LstIn.Count - 1 do
    begin
      inc(i);
      lTmp.CommaText := LstIn.Strings[n];
      lstOut.RowCount := i;
      lstOut.Rows[i-1] := ltmp;
    end;
    lstOut.FixedRows := 1;
    lTmp.Free;
  end;
end;

Three utility functions have been added: Pas2SQLStr, SQL2PasStr, ValueList.

  Pas2SQLStr will convert a Pascal-Style String to an SQL-Style String
    Pas2SQLStr('my mother'''s car') -> "my mother''s car"
  SQL2PasStr will convert an SQL-Style string to a Pascal-Style String
    SQL2PasStr('"my mother''s car") -> 'my mother's car'
  ValueList will Convert ColumnNames, ColumnValues Strings to a Name-Value Pair StringList
    ValueList('ID,Name','1001,FooBar') > ID=1001,Name=Foobar

}

interface

uses Windows, Classes;

type
  TSQLiteExecCallback = function(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer of object; cdecl;
  TSQLiteBusyCallback = function(Sender: TObject; ObjectName: PChar; BusyCount: integer): integer of object; cdecl;
  TOnData = Procedure(Sender: TObject; Columns: Integer; ColumnNames, ColumnValues: String) of object;
  TOnBusy = Procedure(Sender: TObject; ObjectName: String; BusyCount: integer; var Cancel: Boolean) of object;
  TOnQueryComplete = Procedure(Sender: TObject) of object;
  TSQLite = class(TObject)
  private
    fSQLite: Pointer;
    fMsg: String;
    fIsOpen: Boolean;
    fBusy: Boolean;
    fError: Integer;
    fVersion: String;
    fEncoding: String;
    fTable: TStrings;
    fLstName: TStringList;
    fLstVal: TStringList;
    fOnData: TOnData;
    fOnBusy: TOnBusy;
    fOnQueryComplete: TOnQueryComplete;
    fBusyTimeout: integer;
    fPMsg: PChar;
    fChangeCount: integer;
    procedure SetBusyTimeout(Timeout: integer);
  public
    constructor Create(DBFileName: String);
    destructor Destroy; override;
    function Query(Sql: String; Table: TStrings = nil): boolean;
    function ErrorMessage(ErrNo: Integer): string;
    function IsComplete(Sql: String): boolean;
    function LastInsertRow: integer;
    function Cancel: boolean;
    function DatabaseDetails(Table: TStrings): boolean;
    property LastErrorMessage: string read fMsg;
    property LastError: Integer read fError;
    property Version: String read fVersion;
    property Encoding: String read fEncoding;
    property OnData: TOnData read fOnData write fOnData;
    property OnBusy: TOnBusy read fOnBusy write fOnBusy;
    property OnQueryComplete: TOnQueryComplete read fOnQueryComplete write fOnQueryComplete;
    property BusyTimeout: Integer read fBusyTimeout write SetBusyTimeout;
    property ChangeCount: Integer read fChangeCount;
  end;
  function Pas2SQLStr(const PasString: string): string;
  function SQL2PasStr(const SQLString: string): string;
  function QuoteStr(const s: string; QuoteChar: Char = #39): string;
  function UnQuoteStr(const s: string; QuoteChar: Char = #39): string;
  procedure ValueList(const ColumnNames, ColumnValues: String; NameValuePairs: TStrings);

implementation

const
  SQLITE_OK        = 0;  // Successful result
  SQLITE_ERROR     = 1;  // SQL error or missing database
  SQLITE_INTERNAL  = 2;  // An internal logic error in SQLite
  SQLITE_PERM      = 3;  // Access permission denied
  SQLITE_ABORT     = 4;  // Callback routine requested an abort
  SQLITE_BUSY      = 5;  // The database file is locked
  SQLITE_LOCKED    = 6;  // A table in the database is locked
  SQLITE_NOMEM     = 7;  // A malloc() failed
  SQLITE_READONLY  = 8;  // Attempt to write a readonly database
  SQLITE_INTERRUPT = 9;  // Operation terminated by sqlite_interrupt()
  SQLITE_IOERR     = 10;  // Some kind of disk I/O error occurred
  SQLITE_CORRUPT   = 11;  // The database disk image is malformed
  SQLITE_NOTFOUND  = 12;  // (Internal Only) Table or record not found
  SQLITE_FULL      = 13;  // Insertion failed because database is full
  SQLITE_CANTOPEN  = 14;  // Unable to open the database file
  SQLITE_PROTOCOL  = 15;  // Database lock protocol error
  SQLITE_EMPTY     = 16;  // (Internal Only) Database table is empty
  SQLITE_SCHEMA    = 17;  // The database schema changed
  SQLITE_TOOBIG    = 18;  // Too much data for one row of a table
  SQLITE_CONSTRAINT = 19;  // Abort due to contraint violation
  SQLITE_MISMATCH  = 20;  // Data type mismatch
  SQLITEDLL: PChar = 'sqlite.dll';
  DblQuote: Char   = '"';
  SngQuote: Char   = #39;
  Crlf: String     = #13#10;
  Tab: Char        = #9;

var
  SQLite_Open: function(dbname: PChar; mode: Integer; var ErrMsg: PChar): Pointer; cdecl;
  SQLite_Close: procedure(db: Pointer); cdecl;
  SQLite_Exec: function(db: Pointer; SQLStatement: PChar; CallbackPtr: Pointer; Sender: TObject; var ErrMsg: PChar): integer; cdecl;
  SQLite_Version: function(): PChar; cdecl;
  SQLite_Encoding: function(): PChar; cdecl;
  SQLite_ErrorString: function(ErrNo: Integer): PChar; cdecl;
  SQLite_GetTable: function(db: Pointer; SQLStatement: PChar; var ResultPtr: Pointer; var RowCount: Cardinal; var ColCount: Cardinal; var ErrMsg: PChar): integer; cdecl;
  SQLite_FreeTable: procedure(Table: PChar); cdecl;
  SQLite_FreeMem: procedure(P: PChar); cdecl;
  SQLite_Complete: function(P: PChar): boolean; cdecl;
  SQLite_LastInsertRow: function(db: Pointer): integer; cdecl;
  SQLite_Cancel: procedure(db: Pointer); cdecl;
  SQLite_BusyHandler: procedure(db: Pointer; CallbackPtr: Pointer; Sender: TObject); cdecl;
  SQLite_BusyTimeout: procedure(db: Pointer; TimeOut: integer); cdecl;
  SQLite_Changes: function(db: Pointer): integer; cdecl;
  LibsLoaded: Boolean;
  DLLHandle: THandle;
  MsgNoError: String;

function QuoteStr(const s: string; QuoteChar: Char = #39): string;
begin
  Result := Concat(QuoteChar, s, QuoteChar);
end;

function UnQuoteStr(const s: string; QuoteChar: Char = #39): string;
begin
  Result := s;
  if length(Result) > 1 then
  begin
    if Result[1] = QuoteChar then
      Delete(Result, 1, 1);
    if Result[Length(Result)] = QuoteChar then
      Delete(Result, Length(Result), 1);
  end;
end;

function Pas2SQLStr(const PasString: string): string;
var
  n: integer;
begin
  Result := SQL2PasStr(PasString);
  n := Length(Result);
  while n > 0 do
  begin
    if Result[n] = SngQuote then
      Insert(SngQuote, Result, n);
    dec(n);
  end;
  Result := QuoteStr(Result);
end;

function SQL2PasStr(const SQLString: string): string;
const
  DblSngQuote: String = #39#39;
var
  p: integer;
begin
  Result := SQLString;
  p := pos(DblSngQuote, Result);
  while p > 0 do
  begin
    Delete(Result, p, 1);
    p := pos(DblSngQuote, Result);
  end;
  Result := UnQuoteStr(Result);
end;

procedure ValueList(const ColumnNames, ColumnValues: String; NameValuePairs: TStrings);
var
  n: integer;
  lstName, lstValue: TStringList;
begin
  if NameValuePairs <> nil then
  begin
    lstName := TStringList.Create;
    lstValue := TStringList.Create;
    lstName.CommaText := ColumnNames;
    lstValue.CommaText := ColumnValues;
    NameValuePairs.Clear;
    if lstName.Count = LstValue.Count then
      if lstName.Count > 0 then
        for n := 0 to lstName.Count - 1 do
          NameValuePairs.Append(Concat(lstName.Strings[n], '=', lstValue.Strings[n]));
    lstValue.Free;
    lstName.Free;
  end;
end;

function LoadLibs: Boolean;
begin
  Result := False;
  DLLHandle := LoadLibrary(SQLITEDLL);
  if DLLHandle <> 0 then
  begin
    @SQLite_Open := GetProcAddress(DLLHandle, 'sqlite_open');
    if not Assigned(@SQLite_Open) then exit;
    @SQLite_Close := GetProcAddress(DLLHandle, 'sqlite_close');
    if not Assigned(@SQLite_Close) then exit;
    @SQLite_Exec := GetProcAddress(DLLHandle, 'sqlite_exec');
    if not Assigned(@SQLite_Exec) then exit;
    @SQLite_Version := GetProcAddress(DLLHandle, 'sqlite_libversion');
    if not Assigned(@SQLite_Version) then exit;
    @SQLite_Encoding := GetProcAddress(DLLHandle, 'sqlite_libencoding');
    if not Assigned(@SQLite_Encoding) then exit;
    @SQLite_ErrorString := GetProcAddress(DLLHandle, 'sqlite_error_string');
    if not Assigned(@SQLite_ErrorString) then exit;
    @SQLite_GetTable := GetProcAddress(DLLHandle, 'sqlite_get_table');
    if not Assigned(@SQLite_GetTable) then exit;
    @SQLite_FreeTable := GetProcAddress(DLLHandle, 'sqlite_free_table');
    if not Assigned(@SQLite_FreeTable) then exit;
    @SQLite_FreeMem := GetProcAddress(DLLHandle, 'sqlite_freemem');
    if not Assigned(@SQLite_FreeMem) then exit;
    @SQLite_Complete := GetProcAddress(DLLHandle, 'sqlite_complete');
    if not Assigned(@SQLite_Complete) then exit;
    @SQLite_LastInsertRow := GetProcAddress(DLLHandle, 'sqlite_last_insert_rowid');
    if not Assigned(@SQLite_LastInsertRow) then exit;
    @SQLite_Cancel := GetProcAddress(DLLHandle, 'sqlite_interrupt');
    if not Assigned(@SQLite_Cancel) then exit;
    @SQLite_BusyTimeout := GetProcAddress(DLLHandle, 'sqlite_busy_timeout');
    if not Assigned(@SQLite_BusyTimeout) then exit;
    @SQLite_BusyHandler := GetProcAddress(DLLHandle, 'sqlite_busy_handler');
    if not Assigned(@SQLite_BusyHandler) then exit;
    @SQLite_Changes := GetProcAddress(DLLHandle, 'sqlite_changes');
    if not Assigned(@SQLite_Changes) then exit;
    Result := True;
  end;
end;

function SystemErrorMsg(ErrNo: Integer = -1): String;
var
  buf: PChar;
  size: Integer;
  MsgLen: Integer;
begin
  size := 256;
  GetMem(buf, size);
  If ErrNo = - 1 then
    ErrNo := GetLastError;
  MsgLen := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nil, ErrNo, 0, buf, size, nil);
  if MsgLen = 0 then
    Result := 'ERROR'
  else
    Result := buf;
end;

function BusyCallback(Sender: TObject; ObjectName: PChar; BusyCount: integer): integer; cdecl;
var
  sObjName: String;
  bCancel: Boolean;
begin
  Result := -1;
  with Sender as TSQLite do
  begin
    if Assigned(fOnBusy) then
    begin
      bCancel := False;
      sObjName := ObjectName;
      fOnBusy(Sender, sObjName, BusyCount, bCancel);
      if bCancel then
        Result := 0;
    end;
  end;
end;

function ExecCallback(Sender: TObject; Columns: Integer; ColumnValues: Pointer; ColumnNames: Pointer): integer; cdecl;
var
  PVal, PName: ^PChar;
  n: integer;
  sVal, sName: String;
begin
  Result := 0;
  with Sender as TSQLite do
  begin
    if (Assigned(fOnData) or Assigned(fTable)) then
    begin
      fLstName.Clear;
      fLstVal.Clear;
      if Columns > 0 then
      begin
        PName := ColumnNames;
        PVal := ColumnValues;
        for n := 0 to Columns - 1 do
        begin
          fLstName.Append(PName^);
          fLstVal.Append(PVal^);
          inc(PName);
          inc(PVal);
        end;
      end;
      sVal := fLstVal.CommaText;
      sName := fLstName.CommaText;
      if Assigned(fOnData) then
        fOnData(Sender, Columns, sName, sVal);
      if Assigned(fTable) then
      begin
        if fTable.Count = 0 then
          fTable.Append(sName);
        fTable.Append(sVal);
      end;
    end;
  end;
end;

constructor TSQLite.Create(DBFileName: String);
var
  fPMsg: PChar;
begin
  inherited Create;
  fError := SQLITE_ERROR;
  fIsOpen := False;
  fLstName := TStringList.Create;
  fLstVal := TStringList.Create;
  fOnData := nil;
  fOnBusy := nil;
  fOnQueryComplete := nil;
  fChangeCount := 0;
  if LibsLoaded then
  begin
    fSQLite := SQLite_Open(PChar(DBFileName), 1, fPMsg);
    SQLite_FreeMem(fPMsg);
    if fSQLite <> nil then
    begin
      fVersion := SQLite_Version;
      fEncoding := SQLite_Encoding;
      fIsOpen := True;
      fError := SQLITE_OK;
    end;
  end;
  fMsg := ErrorMessage(fError);
end;

destructor TSQLite.Destroy;
begin
  if fIsOpen then
    SQLite_Close(fSQLite);
  fIsOpen := False;
  fLstName.Free;
  fLstVal.Free;
  fSQLite := nil;
  fOnData := nil;
  fOnBusy := nil;
  fOnQueryComplete := nil;
  fLstName := nil;
  fLstVal := nil;
  inherited Destroy;
end;

function TSQLite.Query(Sql: String; Table: TStrings = nil): boolean;
//var
//  fPMsg: PChar;
begin
  fError := SQLITE_ERROR;
  if fIsOpen then
  begin
    fPMsg := nil;
    fBusy := True;
    fTable := Table;
    if fTable <> nil then
      fTable.Clear;
    fError := SQLite_Exec(fSQLite, PChar(Sql), @ExecCallback, Self, fPMsg);
    SQLite_FreeMem(fPMsg);
    fChangeCount := SQLite_Changes(fSQLite);
    fTable := nil;
    fBusy := False;
    if Assigned(fOnQueryComplete) then
      fOnQueryComplete(Self);
  end;
  fMsg := ErrorMessage(fError);
  Result := (fError <> SQLITE_OK);
end;

function TSQLite.Cancel: boolean;
begin
  Result := False;
  if fBusy and fIsOpen then
  begin
    SQLite_Cancel(fSQLite);
    fBusy := false;
    Result := True;
  end;
end;

procedure TSQLite.SetBusyTimeout(Timeout: Integer);
begin
  fBusyTimeout := Timeout;
  if fIsOpen then
  begin
    SQLite_BusyTimeout(fSQLite, fBusyTimeout);
    if fBusyTimeout > 0 then
      SQLite_BusyHandler(fSQLite, @BusyCallback, Self)
    else
      SQLite_BusyHandler(fSQLite, nil, nil);
  end;
end;

function TSQLite.LastInsertRow: integer;
begin
  if fIsOpen then
    Result := SQLite_LastInsertRow(fSQLite)
  else
    Result := -1;
end;

function TSQLite.ErrorMessage(ErrNo: Integer): string;
begin
  if LibsLoaded then
  begin
    if ErrNo = 0 then
      Result := MsgNoError
    else
      Result := SQLite_ErrorString(ErrNo);
  end else
    MessageBox(GetActiveWindow(), 'Library "sqlite.dll" not found.', 'Error loading DLL', MB_OK or MB_ICONHAND or MB_SETFOREGROUND);
end;

function TSQLite.IsComplete(Sql: String): boolean;
begin
  Result := SQLite_Complete(PChar(Sql));
end;

function TSQLite.DatabaseDetails(Table: TStrings): boolean;
begin
  Result := Query('SELECT * FROM SQLITE_MASTER;', Table);
end;

initialization
  LibsLoaded := LoadLibs;
  MsgNoError := SystemErrorMsg(0);

finalization
  if DLLHandle <> 0 then
    FreeLibrary(DLLHandle);

end.

delphilevi 11. Jan 2006 09:10

Re: SQLite Hilfe zu SUM() ??
 
noch was,

wie lang sind die kontonummern?
die gruppierung kann schiefgehen, wenn die Anzahl der Stellen 12 uebersteigt

daher lieber select sum(Betrag+0),'A' || KontoNr from Konto group by 'A' || KontoNr

Gigant02 11. Jan 2006 17:45

Re: SQLite Hilfe zu SUM() ??
 
@Orbmu2k

hmm nun läuft es :)

aber das kann ja auch nicht sinn der sache sein das immer so schreiben zumüssen :(

@delphilevi

ich muss mir das mla durchschaun was du mir da gepostet hast :)

lg, Gigant

delphilevi 11. Jan 2006 20:32

Re: SQLite Hilfe zu SUM() ??
 
der Fehler in der Gruppierung haengt mit der
innerhalb verwendeten Darstellung von integer zusammen (glaub ich :?)
Ist halt ein Bug und wahrscheinlich schwer zu fixen.

Ein anderer Workaround wäre die Kontonummer als varchar zu deklarieren, dann kann man sich das Casten der Werte beim Gruppieren sparen.

Dann ist aber Konto 12345 <> 012345 :(


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:50 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz