open-Befehl

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
Joachim Raap
Beiträge: 143
Registriert: Mo 30. Mär 2020, 12:37

open-Befehl

Beitrag von Joachim Raap »

Hallo, ist es bei einer SQL-Datenbank (MariaDB) eigentlich so, daß mit "select" nach einem "open" immer der erste Satz gelesen wird (falls nicht EOF)?
Ich habe jetzt den merkwürdigen Fall, daß der Kollege mir einen Satz vorlegt, den es gar nicht gibt :x - jedenfalls dann nicht, wenn ich direkt in die Datenbank schaue.
Wie kann das sein??

Joachim Raap
Beiträge: 143
Registriert: Mo 30. Mär 2020, 12:37

Re: open-Befehl

Beitrag von Joachim Raap »

Nachtrag - inzwischen habe ich rausgefunden, daß ich bei meiner Abfrage einen Satz aus einer anderen Tabelle bekomme. Der Satz, der geliefert wird stammt aus einer Tabelle namens "Gruppen". Wie kann das sein; ich frage doch aus der Tabelle "artikel" ab ??

Code: Alles auswählen

                          FMMenu.SQLQuery1.SQL.Text:='SELECT * FROM artikel where aktiv=1 ORDER BY nr;';
                             FMMenu.SQLQuery1.open;
                              while StrToInt(StrArtNr)<StrToInt(EdtArtNr.Text) do
                               begin
                                StrArtNr:=FMMenu.SQLQuery1.FieldByName('Nr').AsString;
                                StrArtBez:=FMMenu.SQLQuery1.FieldByName('Bez').AsString;
 showmessage(StrArtNr+' '+EDTArtNr.Text);
                                if StrArtNr=EdtArtNr.Text
                                 then Fehlermeldung(3)
                                 else FMMenu.SQLQuery1.Next;
                               end; 

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6770
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: open-Befehl

Beitrag von af0815 »

Ist deine query inaktiv (closed), damit du das SQL überhaupt setzen kannst ? Das Schnipsel zeigt nichts davon und ist zu klein um alles zu beurteilen.
StrArtNr was hat die für initiale Inhalte. Das wird zuerst verwendet dann erst zugewiesen. Dann bleibt das ewig in der Schleife, weil das Next durch die Fehlermeldung ausgehebelt wird und du immer am selben Datensatz bleibt, ausser du steigst hart mit einer Exception aus und brichst alles mal ab.
SELECT * FROM
Dazu gibt es von mir schon einige Infos und wenn sowas vorkommt höre ich zu posten auf.
Korrekt ist
SELECT Nr, Bez FROM artikel where aktiv=1 ORDER BY nr;
Zuletzt geändert von af0815 am Di 22. Nov 2022, 13:18, insgesamt 1-mal geändert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10869
Registriert: Mo 11. Sep 2006, 19:01

Re: open-Befehl

Beitrag von theo »

Was sicher merkwürdig ist: Du baust eine Schleife, welche nichts mit dem Resultat der Abfrage zu tun hat.

Code: Alles auswählen

while StrToInt(StrArtNr)<StrToInt(EdtArtNr.Text) do
Was ist das?

Normalerweise geht man so durch das Resultat:

Code: Alles auswählen

 while not SQLQuery1.EOF do
  begin
   Tuwas;
   SQLQuery1.Next;
  end;

Joachim Raap
Beiträge: 143
Registriert: Mo 30. Mär 2020, 12:37

Re: open-Befehl

Beitrag von Joachim Raap »

zu den Fragen:
1. ja af0815, close ist vor der Abfrage gesetzt.
2. StrArt Nr wird 3 Zeilen vorher (nicht mitkopiert....) auf '0' initialisiert
Ich denke aber, daß das mit dem gelieferten Satz nichts zu tun hat, weil der Vergleich erst danach kommt (oder?)
3 .tut mir leid; kann sein, daß Du zu select * schon viel gesagt hast, das kann ich allerdings aus dem Forum nicht abfragen es sei denn, ich lese Deine 5439 Beiträge durch... Dieser Schnipsel ist in der Tat etwas irreführend, weil die Zeilen für die Feldabfragen nach "Nr" und "Bez" nur zur Fehlersuche dienten (deswegen habe ich gesehen, daß das ein Satz aus einer ganz anderen Tabelle ist). Der Datensatz aus der Tabelle 'artikel' hat insgesamt 33 Felder, die dann in einer Listview gezeigt werden (wenn die Bedingungen stimmen); macht ihr das wirklich so, daß im select tatsächlich alle 33 Bezeichner gelistet werden??

Ich kopiere hier noch mal die ganze Methode für diesen Teil hinein - diesmal ohne meine "Hilfszeilen"; der unterstrichene Befehl liefert dann tatsächlich einen Satz aus einer anderen Tabelle. Vielleicht könnt ihr ja war erkennen und helfen

Code: Alles auswählen

procedure TFMArtikel.BTSpeichernClick(Sender: TObject);
  begin
   if (EDTArtBez.Text<>'')
    then begin
          case Modus of
           1: begin
               //Speichern eines neuen Artikels
               if EDTArtNr.Text<>''
                then begin
                      if CBArtzugGrp.ItemIndex<>-1
                       then begin
                             StrArtNr:='0';
                             //Test, ob die Artikelnnummer schon vorhanden ist
                             //in EdtArtNr.Text kann nur 0-9 enthalten (numerisches Feld)
                             FMMenu.SQLQuery1.SQL.Text:='SELECT * FROM artikel where aktiv=1 ORDER BY nr;';
                             FMMenu.SQLQuery1.open;
                              while StrToInt(StrArtNr)<StrToInt(EdtArtNr.Text) do
                               begin
                               [u] StrArtNr:=FMMenu.SQLQuery1.FieldByName('Nr').AsString;[/u]
                                if StrArtNr=EdtArtNr.Text
                                 then Fehlermeldung(3)
                                 else FMMenu.SQLQuery1.Next;
                               end;
                             FMMenu.SQLQuery1.close;
                             if StrToInt(StrArtNr)>StrToInt(EdtArtNr.Text) then
                              //Artikelnummer ist noch nicht vorhanden
                              begin
                               Komma(EdtArtaktEKP.text);
                               EDTArtaktEKP.Text:=PreisOut;
                               Komma(EdtArtaktVKP.text);
                               EDTArtaktVKP.Text:=PreisOut;
                               StrArtzugGrp:=IntToStr(CBArtzugGrp.ItemIndex);
                               StrArtStGrp:=IntToStr(CBArtStGrp.ItemIndex);
                               FMMenu.SQLQuery1.SQL.Text:='insert into artikel (nr,bez,anlg,zugGrp,stgrp,aktEKP,aktVKP,monums,jahresums,vormonums,vorjahresums, '+
                                                                         'ekp1,ekp2,ekp3,ekp4,ekp5,vkp1,vkp2,vkp3,vkp4,vkp5, '+
                                                                         'ekpgueab1,ekpgueab2,ekpgueab3,ekpgueab4,ekpgueab5, '+
                                                                         'vkpgueab1,vkpgueab2,vkpgueab3,vkpgueab4,vkpgueab5,aktiv) '+
                                                                'VALUES ('''+EDTArtNr.Text+''','''+EDTArtBez.Text+''','''+EDTArtAnlg.Text+''','''+StrArtzugGrp+''','''+StrArtStGrp+''','''+EDTArtaktEKP.Text+''','''+EDTArtaktVKP.Text+''', '+
                                                                         '0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1);';
                               FMMenu.SQLQuery1.execsql;
                               FMMenu.SQLTransaction1.Commit;
                               FMMenu.SQLQuery1.close;
                               Fehlermeldung(1);
                               FMMenu.SQLQuery1.SQL.Text:='select * from artikel order by nr;';
                               FMMenu.SQLQuery1.open;
                               LVAnzeigen;
                               Zeile_sichtbar(false);
                              end;
                            end
                       else Fehlermeldung(13);
                     end
                else Fehlermeldung(12);
              end;    

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6770
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: open-Befehl

Beitrag von af0815 »

Joachim Raap hat geschrieben: Di 22. Nov 2022, 15:40 macht ihr das wirklich so, daß im select tatsächlich alle 33 Bezeichner gelistet werden??
Und 33 sind ja auch nicht die Welt, so ab 100 aufwärts wird es interessant. (Für normale Leute > wenn man Maschinenparameter speichert können da schon sehr breite Tabellen zwangsweise herauskommen). Man kann die Statements auch berechnen lassen und so den SQL zusammenbauen. Damit wird die Sache dynamischer und man braucht nicht alles schreiben, besonders dann wenn die Feldnamen einer Logik folgen.

Ja und zwar aus einfachen Gründen. Falls der Irgendwer oder der Niemand Änderungen nach Jahren an der Tabelle vornimmt, so wird sofort klar woher der Fehler kommt und zwar aus dem Select, das gilt natürlich auch für Joins etc. Außerdem kann man rasch abzählen ob man alle hat oder auch definitiv entscheiden das man für die Abfrage von 33 genaugenommen nur 3 braucht und der Rest belastet nur die Verbindung. Das nächste ist, man kann den kompletten Quelltext nach den Spalten absuchen. Man muss sich das auch meistens nicht händisch zusammenbauen. Dafür gibt es die diversen Tools, wo die kompletten Anweisungen schon mal vorgefertigt herausfallen. Und noch was, diese Select * from findet man IMHO nur in Anfängerlektüre, normalerweise nicht professionellen Umfeld.

Hinweis:
* ) LazDataDesktop ist bei Lazarus in den Tools dabei
* ) Kontextmenü einer Query -> Edit alle Statements wenn die verbundene Connection offen ist. Nachteil Create Table Statements gehen dort nicht.

Edit:
Vor dem ersten Open ist kein Close.
Mach vor dem Zuweisen immer ein Clear des SQLStatments.
Verwende für die Fehlersuche den LazLogger und schau nach ob du wirklich im richtigen case Zweig bist und beachte das du bei einem Open oder ExecSQL eine Exception haben kannst, die dich, je nach Programm ganz blöd erwischen kann.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Joachim Raap
Beiträge: 143
Registriert: Mo 30. Mär 2020, 12:37

Re: open-Befehl

Beitrag von Joachim Raap »

.....clear hat geholfen.
Merci

Benutzeravatar
gladio
Beiträge: 223
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: open-Befehl

Beitrag von gladio »

Nimmst du denn die gleiche SQLQuery1 für mehrere Datentabellen?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6770
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: open-Befehl

Beitrag von af0815 »

gladio hat geschrieben: Mi 23. Nov 2022, 06:34 Nimmst du denn die gleiche SQLQuery1 für mehrere Datentabellen?
Schau dir sein Beispiel ein paar Posts vorher an, dann siehst du das.

Und es ist kein Problem das zu machen, wenn man ein paar Kleinigkeiten beachtet.
* ) Man darf die Daten nicht länger brauchen :-) hehe
* ) Immer die Query schließen
* ) die SQL-Statements löschen und die Query zurücksetzen (Clear)
* ) Die neuen SQL-Statements laden
* ) Parameter neu versorgen
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
gladio
Beiträge: 223
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: open-Befehl

Beitrag von gladio »

Ja klar kann man das machen.
Aber damit vereinfacht man sich die ganze Sache ja nicht unbedingt, wohl eher im Gegenteil.
Nicht meine Empfehlung.

Antworten