Datenstruktur: plötzlich anders (Zeos)

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Datenstruktur: plötzlich anders (Zeos)

Beitrag von Aliobaba »

Hallo,

Während meiner Arbeiten an meinem Projekt (MyMemoryDB) fiel mir plötzlich auf, dass DBGrid-Einträge plötzlich nicht mehr der Zahlengröße nach sortiert wurden: alte Eingaben waren in der richtigen Reihenfolge sortiert, die neueren Einträge waren wieder in sich in der richtigen Reihenfolge, diese letzteren folgten aber alle "hinter" den alten Einträgen.

Mein Programm ist erstellt mit "Lazarus" einschließlich der "Zeos-Library" und der Datenbank: "SQLite".

Zunächst suchte ich in meinem Programm selber nach dem Fehler und nachdem ich keine Fehler fand, sah ich mir zunächst mit "SQLiteSpy" und dann mit dem "SQLite Manager" die eingetragenen Daten an. In SQLiteSpy fiel mir dann auf, dass die neueren Daten offenbar in einem anderen Format gespeichert wurden. Es fanden sich immer "Pärchen" mit Zahlen und Buchstaben" anstatt des von mir gewünschten Texteintrags eines Datums in der Form "20130305" (für 5.3.2013). Der SQLite Manager zeigte das Problem deutlicher: Hier wurden die "neueren" Eingaben statt mit hellgrün mit violett unterlegt: Es waren (plötzlich) BLOB-Einträge.

Wissentlich habe ich aber in meinem Programm absolut nichts geändert; alle Felder, die mit dem Datenbanktyp "TEXT" (nicht nur das Datum (sh. Fußnote)) gespeichert werden, wurden nun offenbar plötzlich im "BLOB"-Format abgespeichert. Auch ein anderes Feld der Datenbank, das als "TEXT"-feld abgespeichert wird, wird, wenn es nachträglich verändert (editiert) wurde, dann plötzlich in diesem "BLOB"-Format in der Datenbank abgelegt.

In meinem Programm sind die hier relevanten Feld-Typen immer schon(!!) "TMemoField"'s als BlobType: "ftBlob" (immer schon!). Diese Daten werden also schon "richtig" in die Datenbank reingeschrieben. Mich muss das auch nicht weiter stören, denn die neu eingetragenen Daten werden ja wieder richtig sortiert. Mit diesem neuen Programmverhalten könnte ich also leben.

Ich möchte aber gerne dazulernen und deshalb würde ich gerne wissen, woran es liegen kann, dass die Einträge in die Datenbank jetzt plötzlich in einer anderen Datenstruktur vorgenommen werden als noch vor wenigen Tagen.

Aliobaba

Fußnote: Ich weiß, dass ein Memofeld für das Speichern von nur 8 Zeichen übertrieben ist, aber diese Daten (Recall-Datums-Feld) wurden erst in der späteren Programmierarbeit nötig und mir stand in der mit "Reservefeldern" vorbereiteten Datenbank nur noch ein Feld von Typ "Text" zur Verfügung.
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

MmVisual
Beiträge: 1605
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4.2 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von MmVisual »

Nee, das geht anders.
- Es gibt irgend eine "Parameter Tabelle" in der steht die Version der Datenbank
- Nun startet eine EXE und die liest als erstes diese Version aus
- Wenn die EXE eine neuere Version der Datenbank benötigt, so soll die gefälligst ein Update machen
- Somit wird automatisch jede ältere Datenbank immer der neuesten Programmversion angepasst.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von Aliobaba »

:) :D

Ah, ja!! Danke! dann weiß ich jetzt vielleicht, woran das liegt:

Du weißt ja, dass ich "Deine" Version hier auf meinem PC hüte wie meinen Augapfel :) . Funktioniert nämlich immer noch absolut prima!!

Ich habe vor ca. 1 Woche Lazarus mal probeweise auf einer Virtual-Box(!) mit Zeos installiert . Es hat alles nahezu fast auf Anhieb funktioniert. Beim Starten dieses neu installierten Lazarus auf der VirtualBox habe ich dann die bereits vorhandene Datenbank (SQLite) verwendet zum Ausprobieren.

Mit dieser Datenbank habe ich dann aber später wieder mit "Deiner" Version auf meinem PC (nicht mit der VirtualBox) weiter gearbeitet.
Erklärt das möglicherweise dieses beschriebene Programverhalten?

Vielen Dank!
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

MmVisual
Beiträge: 1605
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4.2 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von MmVisual »

Für Zahlenwerte sollten man Zahlenfelder nehmen, dann werden die auch richtig sortiert gezeigt. Ich weiß jetzt auch nicht (mehr) welche Zeos Version Du installiert hast. Ich meine in der Sortierung wurde mal was geändert. Bei mir wird auch unterschiedlich sortiert, wenn ich einen SQL Befehl mit "ORDER BY" schreibe, je nach Datenbank (SQLite / MySQL) kommen die Daten mit einer anderen Sortierreihenfolge. Die Zeos eigene Sortier-Funktion sortiert nochmal anders. Ist wohl auch abhängig vom verwendeten Zeichensatz.
Eine Text Sortierung sortiert so:
1
10
11
12
2
20
21
22
3
EleLa - Elektronik Lagerverwaltung - www.elela.de

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von Aliobaba »

Hallo MmVisual,

die Sortierung ist eigentlich "nahezu" richtig.
Die "alten", also früher eingetragenen Daten erscheinen am Anfang der Liste
20130401
20140517
10171224
Die neu eingetragene Daten am Ende der Liste,
-- jeweils sauber sortiert, aber erst der Block der "alten" dann der Block der "neuen Daten"

SQLiteSpy zeigt die "alten Einträge so:
20130401
20140517
10171224
und die neuen Einträge ungefähr so:
32 30 31 35 31 32 31 34
32 30 31 33 30 33 31 31
32 30 31 38 30 37 31 55

der SQLite Manger zeigt die Daten ALLe ungefähr so an
20130401
20140517
10171224
auch die neuen Einträge werden in dieser Form angezeigt, habe aber eine violette, keine hellgrüne Farbe, was bedeutet, dass Sie als BLOB abgespeichert werden.
Die "alten" Einträge wurden scheinbar nicht als "BLOB" abgespeichert, obwohl "TMemoField"'s als BlobType: "ftBlob" (immer schon!) in Lazarus angegeben wird.

Wie gesagt, ich kann mit dieser Problematik leben, die neuen Daten werden ja "in sich" richtig sortiert, die alten Einträge kann mn ohne weiteres aus der Datenbank herausnehmen, da es sich ja nur um Recall-Daten handelt. [ http://www.mymemorydb.n-bay.de/ ]

Viele Grüße!
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

MmVisual
Beiträge: 1605
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4.2 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von MmVisual »

Mit welchem Befehlt veranlasst Du die Sortierung der Daten?
EleLa - Elektronik Lagerverwaltung - www.elela.de

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von Aliobaba »

Hallo MmVisual,

in Lazarus mit folgendem Befehl:

Form1.QText.SQL.Text := 'Select * from tText WHERE T2 > 100 ORDER BY T2';
Form1.QText.Open;

Bei der Anlage der Datenbank habe ich "Reservespalten" angelegt. "T2" ist so eine. Die Daten, die ich eingebe werden vorher in eine Textform gewandelt.
Der gesamt Code ist hier:

(ICH BIN ANFÄNGE!!! PROFIS BITTE NICHT LACHEN!!!!)

Code: Alles auswählen

///////////////////////////////////////
/////  Wiedervorlage      
 
procedure TForm1.EdWiederVorlageDblClick(Sender: TObject);
begin
 Form1.Wiedervorlage_DoppKlick;
end;
procedure TForm1.EdWiederVorlageKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
   If (ssCtrl in Shift) then
   begin
     If (Key=VK_Up) then Form1.Wiedervorlage_DoppKlick;
   end;
end;
Procedure TForm1.Wiedervorlage_DoppKlick;
begin
  EdWiederVorlage.Text:='';
  EdWiederVorlage.Color:=clyellow;
end;
 
procedure TForm1.EdWiederVorlageKeyPress(Sender: TObject; var Key: char);
begin
   If (key in [#13]) then
  begin
    DatumFormatieren;   //besser on enter und evtl. onclick  (sonst 2* aufgerufen)
  end;
end;
 
procedure TForm1.DatumFormatieren; // da wird die Eingabe analysiert und evtl in die Datenbank übernommen
 var
 datum: TDate;
 s : string;
 pos1,pos2,posex : integer;
 
begin
  if EdWiederVorlage.Text = '' then    // Recall wird gelöscht
     begin
       Form1.Eingabemodus__ein;
       DB_T2_Datum.Text:='';
       Form1.Eingabemodus__aus;
       Form1.WiedervorstellungZeigen;
       exit;
     end
     else                             // Recall wird geändert oder Eintrag verworfen
     begin
       try    //Eingabe könnte ernst gemeint sein -> prüfen
        datum:=StrToDate( EdWiederVorlage.Text);
        EdWiederVorlage.Text:=datetimetostr(datum); // ist es gültiges Datum?
       except
        ShowMessage('Das Datumsformat ist falsch: '#13#10'Richtig wäre z.B.: 12.7.2015 oder 12.07.15');  // '#13#10'Wenn Sie keine Wiedervorlage wünschen, dann drücken Sie'#13#10'bei einem leeren Eingabefeld bitte nur die Enter-Taste');
        EdWiederVorlage.Text:='keine Änderung';
        EdWiederVorlage.Color:=clSkyBlue;
        DBMemoText.SetFocus;
        exit;
       end;
     end;
 
//  ab jetzt ist das Datum (wahrscheinlich) richtig
 
  Form1.Eingabemodus__ein;
  datum:=StrToDate( EdWiederVorlage.Text);
  DB_T2_Datum.Text:=FormatDateTime('yyyymmdd', datum);
  Form1.Eingabemodus__aus;
  Form1.WiedervorstellungZeigen;  // sortiert anzeigen
end;
 
procedure TForm1.DatumEintragen; // wird bei jedem neu aufgerufenen Schlagwort neu eingetragen
var
  t,m,j,x : string;
begin
if length (DB_T2_Datum.Text) = 8 then  // wird auf richtige Länge geprüft!! Dann ist ein richtiger Eintrag ja vorhanden
 begin
   j:= copy ( DB_T2_Datum.Text,0,4);
   m:= copy ( DB_T2_Datum.Text,5,2);
   t:= copy ( DB_T2_Datum.Text,7,2);
   EdWiederVorlage.Text:= t + '.' + m + '.' + j;
   x:= FormatDateTime('yyyymmdd', now);
   EdWiederVorlage.Refresh;  // eigentlich wohl sinnlose Vorsichtsmaßnahme im Rahmen meiner Fehlersuche
   DB_T2_Datum.Refresh;      // eigentlich wohl sinnlose Vorsichtsmaßnahme im Rahmen meiner Fehlersuche
   if x < DB_T2_Datum.Text then   // Termin mit heutigem Tag vergleichen
   begin
     EdWiederVorlage.Color:=clLime;
   end
   else
   begin
     EdWiederVorlage.Color:=clRed;
   end;
 end
 else
 begin                       //  kein richtiger Eintrag in der Datenbank = Recall ist keiner vergeben
   EdWiederVorlage.Text:=' - - - - - ';
   EdWiederVorlage.Color:=clyellow;
   EdWiederVorlage.Refresh;
 end;
end;
 
procedure TForm1.WiedervorstellungZeigen;  // sortiert anzeigen
begin
  Form1.QText.SQL.Text := 'Select * from tText WHERE T2 > 100 ORDER BY T2';
  Form1.QText.Open;
  Form1.EdWiederVorlage.SetFocus;
end;
 
///// Ende  Wiedervorlage
 

Hier die Datenbankstruktur:

CREATE TABLE "tText"
(
"rID" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
"rTitel" VARCHAR(90) NOT NULL,
"rText" TEXT,
"rHinweis" TEXT,
"rFKRubrik" INTEGER DEFAULT '1', "rDatumerstellt" CHAR, "rDatumgeaendert" CHAR, T1 TEXT, T2 TEXT, T3 TEXT, T4 TEXT, T5 TEXT,
FOREIGN KEY(rFKRubrik) REFERENCES tRubrik(rID) ON DELETE NO ACTION
)

Aber wie oben beschrieben: Eigentlich funktiert alles; es ist nur nicht völlig kompatibel zu den "alten" einträgen

Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

MmVisual
Beiträge: 1605
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4.2 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von MmVisual »

StrToDate() kann eine Exception auslösen und das Programm wird nicht korrekt ausgeführt.
StrToDateDef() kann als zweiten Parameter einen Default-Wert bekommen, der als Ergebnis zurück gegeben wird, falls im String doch nicht was sinnvolles steht und macht keine Exception.

>> "if x < DB_T2_Datum.Text then // Termin mit heutigem Tag vergleichen"
Ein Text vergleichen um das Datum zu analysieren ist wohl auch eher Zufall dass es funktioniert.

Vielleicht nutzt Du doch mal die anderen Feldtypen, wie "DATE" und "INTEGER". Auch ein "VARCHAR(n)" ist für Felder mit weniger als 255 Zeichen Soll-Inhalt (z.B. Tel-Nummer, Ortsnamen usw.) auch an zu raten. Das Memofeld "TEXT" sollte wirklich nur für Text gut sein und nicht dient als allzweck Müllhalde. Schlussendlich machst Du Dir damit das Leben viel einfacher. Ich lerne auch nach über 20 Jahren Programmierung jeden Tag was dazu :)

Um die Tabellenstruktur zu ändern musst Du unter SQLite die Tabelle neu aufbauen, denn die alten Felder kann SQLite nicht löschen. Somit am besten:
- Neue Tabelle mit neuem Name anlegen
- Daten einkopieren
- alte Tabelle löschen
EleLa - Elektronik Lagerverwaltung - www.elela.de

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von Aliobaba »

Danke!! MmVisual,

Vielleicht nutzt Du doch mal die anderen Feldtypen, wie "DATE" und "INTEGER". Auch ein "VARCHAR(n)" ist für Felder mit weniger als 255 Zeichen Soll-Inhalt (z.B. Tel-Nummer, Ortsnamen usw.) auch an zu raten.

Wie gesagt: das benutzte Feld "T2" wurde von mir schon lange vorher "als Reserve" angelegt und wird nun - aus Gründen der Kompatibilität mit Vorversionen - nolens/volens benutzt.
Und: Ein kleines Problem gibt es dabei aber: Das Programm hat mittlerweile einige Anwender.
Und ich habe versprochen, dass die Daten auch bei Udates kompatibel bleiben.

Ich muss also "Kurs halten".

Ein Text vergleichen um das Datum zu analysieren ist wohl auch eher Zufall dass es funktioniert.
Ich wandle das Datum ja in einen exakt definierten Text um; der Vergleich funktioniert jedenfalls problemlos.

StrToDate() kann eine Exception auslösen und das Programm wird nicht korrekt ausgeführt.
Wenn die Exception ausgelöst wird, dann ist das Datum eben nicht in der vorgesehenen Form eingegeben worden und es erfolgt ein Hinweis.

Darf ich meine Frage nochmal stellen:
Mit dieser Datenbank habe ich dann aber später wieder mit "Deiner" Version auf meinem PC (nicht mit der VirtualBox) weiter gearbeitet.
Erklärt das möglicherweise dieses beschriebene Programverhalten?

Viele Grüße
Aliobaba
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

hde
Beiträge: 556
Registriert: Mi 11. Aug 2010, 02:56

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von hde »

sorry dass ich mich einmische obwohl ich keine Erkenntnisse dazu habe, nur Vermutungen.
Ich stelle auch fest, dass nach neueren Updates Daten teilweise anders ausgelesen werden als bisher, konnte aber aus Zeitgründen noch nicht genau ermitteln woran das liegt, ob an Lazarus oder Zeos.
Mit SQLite arbeite ich nicht produktiv, habe aber im Hinterkopf dass dort die Feldtypen nicht wirklich fest vorgegeben sind sondern von SQlite anhand der Daten erkannt werden. Wenn dem so ist, dann wird SQLite den Daten die jetzt anders codiert sind auch einen anderen Feldtyp zuordnen, z.B, jetzt blob statt bisher varchar().
Ich würde empfehlen dies mal zu prüfen.
hde

Aliobaba
Lazarusforum e. V.
Beiträge: 496
Registriert: Di 1. Mai 2012, 09:11

Re: Datenstruktur: plötzlich anders (Zeos)

Beitrag von Aliobaba »

Hallo,

ja, genau den Eindruck hatte ich auch, bin aber mit meinem eher laienhaften Kenntnisstand über diese Materie doch etwas überfordert:

Code: Alles auswählen

der SQLite Manger zeigt die Daten ALLe ungefähr so an
20130401
20140517
10171224
auch die neuen Einträge werden in dieser Form angezeigt, [b][u]haben aber eine violette, keine hellgrüne Farbe, was bedeutet, dass Sie als BLOB abgespeichert werden.
Die "alten" Einträge wurden scheinbar nicht als "BLOB" abgespeichert,[/u][/b] obwohl "TMemoField"'s als BlobType: "ftBlob" [u][b](immer schon!)[/b][/u] in Lazarus angegeben wird.
"MyMemoryDB" ( https://www.heise.de/download/product/mymemorydb-89626 )

Antworten