Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL ANweisung liefert leere Datenmenge (https://www.delphipraxis.net/130098-sql-anweisung-liefert-leere-datenmenge.html)

Moony 3. Mär 2009 12:49

Datenbank: MSAccess, MSSQL, MySQL, DB2, Oracle • Zugriff über: TADOConnection

SQL ANweisung liefert leere Datenmenge
 
Hallo zusammen,

ich versuche über ein Modul nach dem vorhandesein des zu bearbeitenden Datensatzes nachzufragen. Denn während ich meine Datensätze markiere und nicht aktualisiere, kann es sein dass vom einem Host an den Datensätzen was geändert wurde und somit mir zur Bearbeitung nicht mehr zur Verfügung stehen.

Deshalb übergebe ich an mein Modul zwei Listen: Names & Values.
Names beinhaltet die Feldnamen kommasepariert und Values die dazugehörigen Inhalte des aktuellen Datensatzes.

Die Funktion sieht dann folgendermaßen aus:

Delphi-Quellcode:
function FindMyRecord(var Names,Values: PChar): Boolean;
var SQL     : String;
    myTable,
    myConn  : String;
    Ini     : TIniFile;
    myDB    : TADOConnection;
    myDS    : TADODataSet;
    FN, FV  : TStringList;
begin
   Result := false;

  Ini := TIniFile.Create(Project.Name);
  try
    myTable := Ini.ReadString('DatabaseSettings', 'DatabaseTable', '');
    myConn := Ini.ReadString('DatabaseSettings', 'DatabaseFileName', '');
  finally
    Ini.Free;
  end;

  if (myConn = '') or (myTable = '') then
     Exit;

  myDB := TADOConnection.Create(nil);
  myDS := TADODataSet.Create(nil);
  FN  := TStringList.Create;
  FV  := TStringList.Create;
  try
    myDB.ConnectionString := myConn;
    myDB.Open;

    if myDB.Connected then
    begin
      FN.CommaText := String(Names);
      FV.CommaText := String(Values);

      myDS.Connection := myDB;

      SQL := 'SELECT * FROM ' + myTable + ' WHERE ';

      for i := 0 to FN.Count - 1 do
      begin
         SQL := SQL + FN.Strings[i] + '=''' + FV.Strings[i] + '''';

        if i < FN.Count - 1 then
           SQL := SQL + ' AND ';
      end;

      myDS.CommandText := SQL;
      myDS.Open;

      if myDS.RecordCount > 0 then
         Result := true;
    end;
  finally
    FN.Free;
    FV.Free;
    myDB.Free;
    myDS.Free;
  end;
end;
Wenn ich den SQL Befehl ausführe bekomme ich als Recordcount 0 zurück, obwohl der Datensatz definitiv so existiert? Irgendeiner ne Idee wieso?

Gruß, Moony

zack0r 3. Mär 2009 13:07

Re: SQL ANweisung liefert leere Datenmenge
 
Hm ich würd mir einfach am Ende mal die SQL-Anfrage ausgeben lassen, wenn die Schleife die zusammengebaut hat, da stimmt bestimmt irgendwas nich.
Bleibt nicht am ende ein 'AND ' stehen? Und fehlt nicht das Semikolon am Ende der Anfrage? Ich weiß nicht wie genau das dein DBMS nimmt.

zack0r

Jürgen Thomas 3. Mär 2009 13:19

Re: SQL ANweisung liefert leere Datenmenge
 
... und solche String-Verknüpfung für SQL-Befehle gehört sowieso verboten; dafür gibt es die Parameter, die auch in Deiner Situation sinnvoll sind. Jürgen

WoGe 3. Mär 2009 14:54

Re: SQL ANweisung liefert leere Datenmenge
 
..und ich würde meine Tabellen um ein LastModifiedTimestamp erweitern und das durch einen Trigger befüllen.
Dann wüsste man sowas allein aufgrund der Uhrzeit...

Grüsse
wo

Moony 3. Mär 2009 16:01

Re: SQL ANweisung liefert leere Datenmenge
 
@Woge:
Da ich nicht weiß ob es in den Tabellen ein solches Feld gibt, bin ich auf das angewiesen was ich bekomme. Also fällt das schon mal weg. Da ich den Kunden nicht vorgeben kann welche Felder sie sich bauen.

@Jürgen:
Warum ist der SQL Befehl nicht richtig? Es ist richtig zusammengesetzt und führt zu keinerlei Fehlern!

@zack:
Ich habe mir die SQL Anweisung angeschaut bevor sie ausgeführt wird. Wenn ein AND zuviel da stünde, würde der Befehl an sich nciht ausgeführt werden und in eine Exception laufen. Was aber nicht der Fall ist. Die Datenmenge liefert mir einen Recordcount von 0 zurück.

WoGe 3. Mär 2009 16:16

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Moony
Es ist richtig zusammengesetzt und führt zu keinerlei Fehlern!

Wenn die Frage richtig ist, könnte dann 0 nicht auch die richtige Antwort sein?

Gruss
wo

Moony 3. Mär 2009 16:34

Re: SQL ANweisung liefert leere Datenmenge
 
Der Datensatz existiert genauso in der Form wie ich ihn angefragt habe. Ich habe in der Zwischenzeit keinerleio Änderungen vorgenommen.

hoika 3. Mär 2009 17:07

Re: SQL ANweisung liefert leere Datenmenge
 
Hallo,

RecordCount ist keine gute Idee.
Du muss nichts drinstehen,

Probier mal select count(*)


Heiko

Moony 4. Mär 2009 08:01

Re: SQL ANweisung liefert leere Datenmenge
 
Der COUNT Befehl liefert ebenfalls 0 zurück.

ULIK 4. Mär 2009 08:18

Re: SQL ANweisung liefert leere Datenmenge
 
Dann ist auch kein Datensatz da, der der entsprechenden Where-Bedingung entspricht. Laß Dir doch mal das komplette generierte SQL-Statement ausgegeben und führ es dann per Hand aus. Vieleicht siehst Du dann, warum keine Daten geliefert werden.
Abgesehen davon: kann es sein, daß der Host den Record erzeugt hat, Du ihn aber noch nicht sehen kannst, weil er die Daten noch nicht commited hat? Oder umgekehrt, daß die Daten nicht gefunden werden, WEIL der Host inzwischen geändert und commited hat?

Grüße,
Uli

Bernhard Geyer 4. Mär 2009 08:24

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von WoGe
Zitat:

Zitat von Moony
Es ist richtig zusammengesetzt und führt zu keinerlei Fehlern!

Wenn die Frage richtig ist, könnte dann 0 nicht auch die richtige Antwort sein?

Vor allem da bei Nicht-Verwendung von Parametern teilweise die Queries je nach DBMS bei Sonderzeichen nicht korrekt ausgewertet werden (bzw. anders interpretiert werden als du denkst).

Um welche DBMS genau handelt es sich? Je nach DBMS hat der Zugriff über ADO (und evtl. ODBC) "komische" Effekte.

Moony 4. Mär 2009 08:33

Re: SQL ANweisung liefert leere Datenmenge
 
Im Moment Filemaker, aber das muß auch für Acces, SQL, MySQL, und Oracle gelten. Dafür gibts auf jeden Fall überprüfungen. Aber grundsätzlich muß das ja erst mal funktionieren. Wenn ich nach der Existenz eines Datensatzes abfrage mit einer Bedingung aller Felder und deren Inhalte, dann muß wenn nichts geändert wurde, der Datensatz zurückgeliefert werden.

ULIK 4. Mär 2009 08:39

Re: SQL ANweisung liefert leere Datenmenge
 
Laß Dir doch mal so ein Statement ausgeben und poste es hier. Vieleicht sieht man ja daran etwas.

Uli

Moony 4. Mär 2009 09:28

Re: SQL ANweisung liefert leere Datenmenge
 
SQL-Code:
SELECT COUNT(*) FROM Stammdaten WHERE CM_REC_NO='3' AND Nachname='Meyer' AND Vorname='Helga' AND Funktion='Project Manager' AND Firma='Meyer KG' AND Strasse='Signaalrood 57' AND PLZ='83834' AND Stadt='Duesseldorf' AND Telefon='+49-79-360 11 60' AND Fax='+49-79-360 11 50' AND Email='' AND Datum='01.01.2002' AND Gueltigkeit='31.12.2005' AND Tag='0' AND Geschlecht='F' AND Land='Deutschland' AND Geburtsdatum='24.08.1975' AND Logo='Abteilung A' AND CM_Image='3.jpg' AND CM_Sign='' AND CM_Layout='Video2'

Bernhard Geyer 4. Mär 2009 09:31

Re: SQL ANweisung liefert leere Datenmenge
 
Datumsangaben nicht als Parameter zu setzen ist immer ein Quell von Problemen. Evtl. erwartet Filemaker hier ein anderes Format (US/ISO/...)

DeddyH 4. Mär 2009 09:33

Re: SQL ANweisung liefert leere Datenmenge
 
Wenn es bei Filemaker eine Art SQL-Editor gibt, kann man das Statement ja dort einmal eingeben und schauen, wie die Ergebnismenge aussieht.

ULIK 4. Mär 2009 09:37

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Moony
SQL-Code:
SELECT COUNT(*) FROM Stammdaten WHERE CM_REC_NO='3' AND Nachname='Meyer' AND Vorname='Helga' AND Funktion='Project Manager' AND Firma='Meyer KG' AND Strasse='Signaalrood 57' AND PLZ='83834' AND Stadt='Duesseldorf' AND Telefon='+49-79-360 11 60' AND Fax='+49-79-360 11 50' AND Email='' AND Datum='01.01.2002' AND Gueltigkeit='31.12.2005' AND Tag='0' AND Geschlecht='F' AND Land='Deutschland' AND Geburtsdatum='24.08.1975' AND Logo='Abteilung A' AND CM_Image='3.jpg' AND CM_Sign='' AND CM_Layout='Video2'

Sind das wirklich alles String-Felder? CM_REC_NO würde ich jetzt eher auf ein NUMBER Feld tippen. Außerdem: Wenn in dem Feld CM_Sign NULL steht, dann ist CM_Sign='' immer falsch, da '' <> NULL

Vieleicht hilft Dir das weiter.

Blup 4. Mär 2009 11:39

Re: SQL ANweisung liefert leere Datenmenge
 
Ich tippe auf NULL-Zustand im Feld Email oder CM_Sign (NULL <> '').
Entferne einfach nacheinander jeweils eine Bedingung, bis eine Ergebnismenge geliefert wird.
Dann dürfte die Ursache leichter einzugrenzen sein.

Moony 4. Mär 2009 12:17

Re: SQL ANweisung liefert leere Datenmenge
 
Bei dieser SQL Anweisung handelt es sich um eine Access Datenbank und die Felder sind nicht alles Textfelder.
Was den Filemaker betrifft, dort gibt es keinerlei Möglichkeit einen SQL Befehl auszuprobieren.
Das mit dem NULL könnte eine Möglichkeit sein. Das könnte man dann mit einer OR Verknüpfung verbinden.

Jürgen Thomas 4. Mär 2009 12:18

Re: SQL ANweisung liefert leere Datenmenge
 
Also zum dritten Mal nach den Antworten in #3 und #11: Benutze Parameter, und die Probleme mit falschen Hochkommata und Datumsformaten gibt es nicht mehr! Du musst Dich dann nur noch um die NULL-Werte kümmern. Jürgen

Moony 4. Mär 2009 12:26

Re: SQL ANweisung liefert leere Datenmenge
 
Welche Parameter?

ULIK 4. Mär 2009 12:32

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Moony
Welche Parameter?

Sag mal, kann es sein, daß Du mit Datenbanken noch nicht viel gemacht hast? Dann würd ich sagen, schau Dir erst mal ein DB-Tutorial an.
Parameter: Du sollst die Werte der Felder als Parameter in die Query einfügen
DB: Ja was denn nun, Access oder Filemaker? :gruebel:

Grüße,
Uli

Bentissimo 4. Mär 2009 12:58

Re: SQL ANweisung liefert leere Datenmenge
 
Hallo zusammen,

also ich finde die Variante eines dynamischen SQL-Strings nicht schlecht. Manchmal ist die Verwendung sogar unumgänglich. Man denke z.B. nur an die Existenz von ExecuteImmediate in Oracle für genau solche Fälle.

Allerdings sind als String übergebene Datumsfelder immer zumindest verdächtig. Selbst wenn es am Ende tatsächlich mit mehreren Datenbanken klappen sollte, kann u.U. eine andere Spracheinstellung auf einem anderen DB-Server oder sogar nur eine andere Landeseinstellung des Rechners das gesamte Kartenhaus zum Einsturz bringen.

Die Fehlersuche in einem anscheinend sauber laufenden Programm, das aber in einer anderen Umgebung plötzlich und unerwartet aussteigt, kann einen buchstäblich in den Wahnsinnn treiben.

Also würde ich vorschlagen, Du nimmst Dir den Rat von ULIK zu Herzen. Falls das aber aus irgendeinem Grunde nicht möglich sein sollte, ist äußerste Sorgfalt beim Erstellen des SQL-Statements vonnöten.

Ich kenne FileMaker zwar nur dem Namen nach, aber dass es dort keine Möglichkeit geben soll, seine SQL-Statements zu testen kann ich gar nicht glauben. Ein adäquates Tool für diesen Zweck würde ich in jedem Fall auch empfehlen. Ich bin auch ziemlich sicher, dass Du damit dem Problem relativ schnell auf die Schliche kommen wirst.

Viel Glück!

Gruß,
Stephan

Bernhard Geyer 4. Mär 2009 13:03

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Bentissimo
also ich finde die Variante eines dynamischen SQL-Strings nicht schlecht. Manchmal ist die Verwendung sogar unumgänglich.

Für diesen fall aber nicht! Man kann auch dynamische SQL-Strings mit Parametern aufbauen!

borwin 4. Mär 2009 13:11

Re: SQL ANweisung liefert leere Datenmenge
 
SQL-Code:
CM_Sign=''
wenn im Feld ein NULL steht wirst Du nichts finden oder Du schreibst
SQL-Code:
CM_Sign IS NULL
Zerflücke Deinen SQL-String und teste Stück für Stück.
Datum und Zeit sind auch immer bekannte Fehler.
SQL-Code:
Geburtsdatum='24.08.1975'
Access will hier ein # vor und nach dem Datum, wenn Du es direkt zur
Datenbank durchreichst. Eine Fehlermeldung kommt bei Deiner Schreibweise nicht, findet aber auch keinen Datensatz.

Gruß Hartmuth

Moony 4. Mär 2009 13:20

Re: SQL ANweisung liefert leere Datenmenge
 
Welche Datenbank das jetzt ist, ist irrelevant, wichtig ist erstmal dass es grundsätzlich funktiert. Anschließend soll es für unterschiedliche funktionieren!

Ich habe schon mehrfach mit Datenbanken gearbeitet, aber mit Parameter bzw. variablen Paramtern noch nicht.

Ich werde versuchen nach Datentyp zu erfragen und dann die richtigen Werte zu setzen. Andererseits bei einem leeren Inhalt nach NULL ebenfalls zu überprüfen.

Bernhard Geyer 4. Mär 2009 13:22

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Moony
Welche Datenbank das jetzt ist, ist irrelevant, wichtig ist erstmal dass es grundsätzlich funktiert. Anschließend soll es für unterschiedliche funktionieren!

Viel Spaß damit das sich jedes DBMS etwas anders damit. Wenn eine Abfrage bei einer DB funktioniert heißt es nicht das sie bei einer anderen Funktioniert. Und ohne Verwendung von parametrisierten Abfragen noch viel weniger.

WoGe 4. Mär 2009 13:24

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Moony
SQL-Code:
SELECT COUNT(*) FROM Stammdaten WHERE CM_REC_NO='3' ....

Wenn ich Moony's ursprüngliche Frage richtig verstehe will er doch nur wissen ob sein Datensatz unverändert existiert.
Sollte das Feld CM_REC_NO ein PK sein, ist es doch sinnvoller die Be(Aus)wertung die er machen möchte in der Funktion selber durchzuführen.
Das hätte auch den Vorteil, dass sämtliche Inhalte in dem Format vorliegen die er eh schon hat und zusätzlich kann er einzelne Felder darauf untersuchen ob er sie ändern darf.

deswegen würde sich folgendes anbieten
SQL-Code:
 SELECT * FROM Stammdaten WHERE CM_REC_NO= :AlteRecNo
Gruss
wo

Moony 4. Mär 2009 13:29

Re: SQL ANweisung liefert leere Datenmenge
 
@Bernhard:
Ich weiß dass es zwischen den DBMS Unterschiede gibt. Wie soll ich das denn deiner Menung nach parametrisieren? Ich weiß nicht wie das geht. Hatte ich aber schon erwähnt...

@Woge:
Prinziell könnte man das auch so machen. Was ist wenn ich das Indexfeld nicht kenne? Oder schlimmer es gibt kein Indexfeld?

WoGe 4. Mär 2009 13:55

Re: SQL ANweisung liefert leere Datenmenge
 
Hat die Tabelle einen PK reicht es völlig alle PK relevanten Felder abzufragen.
Hat sie keinen: Ist ein Konstruktionsfehler....

Das gilt eigentlich auch für das nichtvorhandensein eines ID-Feldes :wink:

gruss
wo

hoika 4. Mär 2009 14:09

Re: SQL ANweisung liefert leere Datenmenge
 
Hallo,

um mal zu den Parametern zu kommen:

Delphi-Quellcode:
with Query do
begin
  SQL.Clear;
  SQL.Add('Select * From Stammdaten');
  SQL.Add('Where Name=:Name');
  ParamByName('Name').AsString:= 'Juhu';
  Open;
  try
    if QueryIsNotEmpty ...
  finally
    Close;
  end;
end;
sieht hübsch aus, keine blödes ""

und nun weiter


Delphi-Quellcode:
with Query do
begin
  SQL.Clear;
  SQL.Add('Select * From Stammdaten');
  SQL.Add('Where Datum=:TheDate');
  ParamByName('TheDate').AsDateTime:= EncodeDate(2009,3,4);
  Open;
  try
    if QueryIsNotEmpty ...
  finally
    Close;
  end;
end;
Das Datum wird auf jeden Fall korrekt übergeben,
egal wie es intern gespeichert wird.

Ein weiterer Vorteil, Prepare.

Delphi-Quellcode:
with Query do
begin
  SQL.Clear;
  SQL.Add('Select * From Stammdaten');
  SQL.Add('Where Name=:Name');
  Prepare;
  for i:= 1 to 5 do
  begin
    ParamByName('Name').AsString:= 'Juhu'+IntToStr(i);
    Open;
    try
      if QueryIsNotEmpty ...
    finally
      Close;
    end;
  end;
end;
Die Query muss nur 1 mal prepared werden (das dauert je nach Komplexität der Query etwas),
wird dann 5mal mit unterschiedlichen Parametern benutzt.
Je nach DB bringt das ne Menge Geschwindigkeit (unter Firebird bei mir + 50%)


Noch mal zu PK kenne ich nicht, Indexfeld auch nicht.
Den PK bekommt man u.U. raus (steht in den System-Tabellen)

Um Änderungen an einem Datensatz zu erkennen, deen Felder du erst zur Laufzeit kennst,
dessen DB du auch erst zur Laufzeit kennst, dessen DB-Struktur du nicht ändern kannst
-> gute Nacht. ;)

Ne, im Ernst.

Schau dir mal das NULL-Tutorial unter ibphoenix.com an,
ist nicht so einfach.

Ich würde viell. den Datensatz des PK (er muss da sein !!!)
komplett laden und mit dem alten (vorher sichern) vergleichen.




Heiko

Moony 4. Mär 2009 16:30

Re: SQL ANweisung liefert leere Datenmenge
 
Aber woher soll ich wissen welches Feld welchen Typ hat? Ich muß doch einmal alle Felder auslesen und bei jedem Feld den Typ erfragen. Nur dann kann ich doch die Parameter füllen.

Was macht die Funktion Prepare? Denn beim TADODataSet gibts diese Funktion nicht.

Bernhard Geyer 4. Mär 2009 16:37

Re: SQL ANweisung liefert leere Datenmenge
 
Zitat:

Zitat von Moony
Aber woher soll ich wissen welches Feld welchen Typ hat?

Wie willst du überhaupt wissen ob für ein Feld dessen Typ du nicht kennst ein "=" anwendbar ist? Schon mal probiert auf eine (n)text-Feld bei MS SQL Server eine "=" anzuwenden? Freu dich auf die Fehlermeldung ...

hoika 4. Mär 2009 17:22

Re: SQL ANweisung liefert leere Datenmenge
 
Hallo,

was du willst, geht einfach nicht.
Akzeptier es einfach.
Du musst schon irgendwas über die DB/Tabelle wissen.

Die Datentypen einer Tabelle stehen in den System-Tabellen
der jeweiligen Datenbank.
Es gibt aber keine einheitliche regelung.
Da macht jeder DB-Hersteller, was er will.


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:45 Uhr.

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