Entwickler-Ecke

Datenbanken - Keine Datensätze?


D. Annies - Do 04.02.10 20:27
Titel: Keine Datensätze?
Hi, Delpher,

wer kann mir mal sagen, warum ich die Meldung bekomme, dass es 0 Datensätze sind? (es sind 741)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
procedure TForm1.btnTestClick(Sender: TObject);
var  Notes: String;
begin
  slDBPath := ExtractFilepath(application.exename) + 'dbSch.db';
  sldb := TSQLiteDatabase.Create(slDBPath);
  showmessage('SchulTabAn geladen');
  try
    if not sldb.TableExists('SchulTabAn'then
    begin
      sSQL := 'CREATE TABLE SchulTabAn ([Name] VARCHAR (50), [Vorname] VARCHAR (50), [Klasse] VARCHAR(10));';
      sldb.execsql(sSQL);

      sldb.BeginTransaction;  //begin a transaction
        sSQL := 'INSERT INTO SchulTabAn(Name,Vorname,Klasse) VALUES ("Annies","Detlef", "11a");';
        sldb.ExecSQL(sSQL);
        sSQL := 'INSERT INTO SchulTabAn(Name,Vorname,Klasse) VALUES ("Annies","Almut", "11a");';
        sldb.ExecSQL(sSQL);
      sldb.Commit;  //end the transaction
    end
    else showmessage('Tabelle ' + 'SchulTabAn' + ' existiert');

    sltb := slDb.GetTable('SELECT * FROM SchulTabAn');  //query the data
    showmessage(inttostr(sltb.count) + 'DS');  // Meldung 0 Datensätze!
    try
      if sltb.Count > 0 then
      begin
        showmessage(inttostr(sltb.count));
        ebID.Text     := '';
        ebName.Text   := sltb.FieldAsString(sltb.FieldIndex['Name']);    //display first DS
          showmessage('hi1');
        ebNumber.Text := sltb.FieldAsString(sltb.FieldIndex['Vorname']);
          showmessage('hi2');
        notes         := sltb.FieldAsString(sltb.FieldIndex['Klasse']);
          showmessage('hi3');
        memNotes.Text := notes;
          showmessage('hi4');
      end
      else showmessage('keine DS');
    finally
      sltb.Free;
    end;
  finally
    sldb.Free;
  end;
end;


Danke, Detlef


mkinzler - Do 04.02.10 21:26

Kommt wirklich kein Ergebnis, oder ist nur Count 0?


D. Annies - Do 04.02.10 21:45

Hi, Markus,

gute Frage:
Codeschnipsel:


Delphi-Quelltext
1:
2:
 sltb := slDb.GetTable('SELECT * FROM SchulTabAn');  //query the data
    showmessage(inttostr(sltb.count) + 'DS');  // Meldung 0 Datensätze!


Also ich bekomme die Meldung: 0 DS siehe oben

??


mkinzler - Do 04.02.10 21:51

Die Frage war aber, ob dieses Count auch stimmt. Bei manchen Zugriffskomponenten wird diese Eigenschaft nicht richtig gesetzt oder zeigt die Anzahl der gefetchten DS an.


D. Annies - Do 04.02.10 22:04

Ja Markus, da wird etwas nicht richtig angegeben, hast du eine Idee, wie es richtig und sicher gehen kann?

Gruß, Detlef

P.S.
ich habe jetzt mal gesetzt:


Delphi-Quelltext
1:
sltb := slDb.GetTable('SELECT count (*) FROM SchulTabAn');                    


Jetzt sind (ist) es 1 (ein) Datensatz

ahu


mkinzler - Do 04.02.10 22:10

Explizit abfragen


D. Annies - Do 04.02.10 22:12

Oh, da hat sich was überschnitten, aber ich weiß leider nicht, wie du explizit meinst.


mkinzler - Do 04.02.10 22:27

Genau das.


Bernhard Geyer - Do 04.02.10 22:34

Ich vermute das die TSQLiteDatabase einen "Serverseitigen" Curser verwendet (ist ja auch sinnvoll bei serverlosen DB wie Sqlite). Jedoch ist bei diesem Cursertyp die Count-Eigenschaft so lange ungültig/falsch bis du bis zum letzten Datensatz navigiert hast und die gesamten Datensätze am Client (hier in deinem sltb-Cache) gelandet ist. Nur bei einem synchronen clientseitigen Curser hast du sofort eine gültige Anzahl Count. Aber u.U. dauert das Öffnen der Query auch mehrer Sekunden (Minuten).

Bei richtigen SQL-Servern ist dies auch ein sehr gewünschtes Verhalten. Z.B. du hast eine Oracle-DB mit einigen TB an Daten. Deine Query würde sagen wir mal 100.000 Datensätze liefern und braucht bis zum vollständigen Aufbau (trotz 100 GB RAM und mehrern Quad-Cores) 10 Minuten. Jedoch willst du die Verarbeitung schon beim ersten Datensatz beginnen da dieser Unabhängig von den noch 99.999 weiter ist. So kann der Aufbau der Ergebnismenge parallel zur Abarbeitung im Client erfolgen.


D. Annies - Do 04.02.10 23:33

Hi, Bernhard, das war mir neu, aber du hast es gut erklärt.

Markus, dich verstehe ich explizit (noch) nicht. :lol: :lol: :lol:

Don't worry Det ..


mkinzler - Do 04.02.10 23:48

Mit explizit meinte ich das select count ...
Und das was Berhard detailiert erklärt hat, war die Anzahl der gefetchten Records


D. Annies - Fr 05.02.10 07:00

Ah, jetzt weiß ich, wie du es gemeint hast, aber die DS-Anzahl wird ja immer noch nicht richtig ausgegeben.


Robert.Wachtel - Fr 05.02.10 11:01

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
Ah, jetzt weiß ich, wie du es gemeint hast, aber die DS-Anzahl wird ja immer noch nicht richtig ausgegeben.

Du sollst nicht die Anzahl der Datensätze von


SQL-Anweisung
1:
SELECT COUNT(*) FROM Tabelle                    


auslesen - das ist immer(!) einer.

Du sollst den Wert von COUNT(*) auslesen.


SQL-Anweisung
1:
SELECT COUNT(*) AS Anzahl FROM Tabelle                    



Delphi-Quelltext
1:
meineQuery.FieldByName('Anzahl').AsInteger                    


D. Annies - Fr 05.02.10 14:29

Ach so,
danke, Robert
Gruß, Detlef


D. Annies - Fr 05.02.10 22:37

Hi, Delpher,

so langsam bekomme ich die Krise: Habe ich denn SQLite3 falsch/unvollständig installiert?
Der folgende Code funktioniert noch immer nicht, obwohl er es - auch nach einem Script, das ich eingesehen habe- tun müsste.
Ich kenne es sonst so, dass noch ein Package installiert werden muss, das habe ich hier nicht, ich kann einfach Variable wie eine SQLiteQuery namens SQLiQy deklarieren, aber nicht entsprechend aufrufen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
// ..............................

var  Form1: TForm1;
     slDBpath: string;
     sldb    : TSQLiteDatabase;
     sltb    : TSQLiteTable;
     SQLiQy  : TSQLiteQuery;
     sSQL    : String;
     iID     : integer;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
  opendialog1.InitialDir := ExtractFilepath(application.exename);
  showmessage(opendialog1.InitialDir);

  // Provider=MSDASQL.1;Persist Security Info=False;Data Source=dbSchule
    // bzw.
  // Provider=MSDASQL.1;Persist Security Info=False;Data Source=dbSchule;
            //Extended Properties="DSN=dbSchule;
            //Database=D:\Daten_An\Delphi\sqliteDBdelphi\dbSch.db;
            //StepAPI=0;SyncPragma=;NoTXN=0;Timeout=;ShortNames=0;LongNames=0;
            //NoCreat=0;NoWCHAR=0;JournalMode=;LoadExt=;"

end;

procedure TForm1.btnTestClick(Sender: TObject);
var  Notes   : String;
    NrOfRecs : integer;
begin
  slDBPath := ExtractFilepath(application.exename) + 'dbSch.db';
  sldb := TSQLiteDatabase.Create(slDBPath);
  showmessage('SchulTabAn geladen');
  try
    if not sldb.TableExists('SchulTabAn'then
    begin
      sSQL := 'CREATE TABLE SchulTabAn ([Name] VARCHAR (50), [Vorname] VARCHAR (50), [Klasse] VARCHAR(10));';
      sldb.execsql(sSQL);

      sldb.BeginTransaction;  //begin a transaction
        sSQL := 'INSERT INTO SchulTabAn(Name,Vorname,Klasse) VALUES ("Annies","Detlef", "11a");';
        sldb.ExecSQL(sSQL);
        sSQL := 'INSERT INTO SchulTabAn(Name,Vorname,Klasse) VALUES ("Annies","Almut", "11a");';
        sldb.ExecSQL(sSQL);
      sldb.Commit;  //end the transaction
    end
    else showmessage('Tabelle ' + 'SchulTabAn' + ' existiert');

    sltb := slDb.GetTable('SELECT count (*) As DSAnzahl FROM SchulTabAn');  //query the data
    showmessage(inttostr(sltb.count) + 'DS');

    SQLiQy.SQL := 'select count(*) from SchulTabAn' ;
    sldb.ExecSQL(SQLiQy.SQL);
    // NrOfRecs := SQLiQy.Fieldbyname('DSAnzahl').AsInteger;  // dieser Aufruf klappt nicht;
    showmessage(inttostr(NrOfRecs) + 'DS');

    SQLiQy.SQL := 'SELECT * FROM SchulTabAn';  //query the data
    sldb.ExecSQL(SQLiQy.SQL);
    try
      if sltb.Count > 0 then
      begin
        showmessage(inttostr(sltb.count));
        ebID.Text     := '0';
          showmessage('hi0');
        ebName.Text   := sltb.FieldAsString(sltb.FieldIndex['Name']);    //klappt nicht (display first DS)
          showmessage('hi1');
        ebNumber.Text := sltb.FieldAsString(sltb.FieldIndex['Vorname']); // klappt nicht, Prg steigt vorher aus
          showmessage('hi2');
        notes         := sltb.FieldAsString(sltb.FieldIndex['Klasse']);
          showmessage('hi3');
        memNotes.Text := notes;
          showmessage('hi4');
      end
      else showmessage('keine DS');
    finally
      sltb.Free;
    end;
  finally
    sldb.Free;
  end;
end;

procedure TForm1.AddSatzClick(Sender: TObject);
begin
  sldb.BeginTransaction;  //begin a transaction
    sSQL := 'INSERT INTO SchulTabAn(Name,Vorname,Klasse) VALUES ("Annies","Detlef","11a");';
    sldb.ExecSQL(sSQL);
  sldb.Commit;  //end the transaction
end;

// ..................


So ein kleines Progrmmierbaby mit Datenbanken bin ich ja nun auch nicht mehr ...

Wer kann mir da raushelfen?
Detlef


Xentar - Fr 05.02.10 22:43

Und die Fehlermeldung?

Ich kenn SQL Lite nicht, aber muss man sltb nicht normalerweise vorher createn? Oder macht das GetTable automatisch?


D. Annies - Sa 06.02.10 00:03

Hi, Xentar,

das habe ich jetzt auf deinen Hinweis hin auch mal gemacht, ohne Erfolg.
Ich hatte gedacht, SQLite könnte jetzt mal eine Alternative werden zur BDE,
aber KV.
Scheint ja auch nicht wirklich viele Benutzer davon zu geben, siehe Meldungen.

Bleibt wohl doch nur Firebird, oder?

Gruß, Detlef


Robert.Wachtel - Sa 06.02.10 09:38

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
[...] Der folgende Code funktioniert noch immer nicht, [...]

Sehr exakte Fehlerbeschreibung...

Zitat:
[...]

Delphi-Quelltext
1:
2:
3:
4:
    SQLiQy.SQL := 'select count(*) from SchulTabAn' ;
    sldb.ExecSQL(SQLiQy.SQL);
    // NrOfRecs := SQLiQy.Fieldbyname('DSAnzahl').AsInteger;  // dieser Aufruf klappt nicht;
    showmessage(inttostr(NrOfRecs) + 'DS');

[...]

Sicher, dass ExecSQL die richtige Methode ist, wenn man eine Ergebnismenge zurückerwartet?

Und SQLiQy.Fieldbyname('DSAnzahl').AsInteger kann ja nicht funktionieren, wenn es in der Ergebnismenge gar kein Feld namens DSAnzahl gibt.


SQL-Anweisung
1:
select count(*) AS DSAnzahl from SchulTabAn                    


D. Annies - Sa 06.02.10 14:40

Dank für deine Mühe, Robert (und an die anderen) aber hier scheint mir ein
grundsätzlicheres Problem [bei mir] vorzuliegen.

Gruß, Detlef