Entwickler-Ecke

Datenbanken - SQL Abfrage Parameter .... hat keinen Standardwert


Arne Danikowski - Do 29.04.10 09:25
Titel: SQL Abfrage Parameter .... hat keinen Standardwert
Hallo, ich habe mit eine Prozedur zusammengestellt. Es sollen alle Datensätze gelöscht werden, die in der Tabelle "PAPIEK" den Wert 'JA' enthalten:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TJP_Main.Datenloeschen(Wert, Feld: string);
begin
  begin
    DM.JPQuery.SQL.Text := 'SELECT * FROM JP WHERE ' + feld + '=' +wert;
    DM.JPQuery.Open;
    DM.JPQuery.First;
    while not DM.JPQuery.EOF do begin
      with DM.JPQuery do begin
        edit;
        delete;
        next;
        edit;
        delete;
      end;
    end;
    DM.JPQuery.SQL.Text :=('Select * From JP Where NOT (Archiv = (''JA'') OR Papierk = (''JA'') OR Vermittelt = (''JA'')) order by Name');
    DM.JPQuery.Open;
  end;
end;


Über einen Button wird die Funktion aufgerufen:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TJP_Main.PKLEOSCHClick(Sender: TObject);
Var wert,feld :String;
begin
    feld:='papierk';
    Wert:='JA';
   if MessageDlg('ACHTUNG! Sollen alle Datensätze im Papierkorb unwiederruflich gelöscht werden?', mtConfirmation, [mbOK, mbCancel], 0) = mrOK
    then
    Datenloeschen(Feld,Wert)
  else
    show;
end;


Beim ausführen erhalte ich die Meldung:
Der Parameter JA hat keinen Standardwert.

Es muss an der SQL Abfrage liegen. Trage ich in der Prozedur die Werte direkt ein, funktioniert es.
Also mit

Delphi-Quelltext
1:
DM.JPQuery.SQL.Text := 'SELECT * FROM JP WHERE  papierk = ''JA'' order by name';                    


Hat jemand einen Rat?


thepaine91 - Do 29.04.10 09:29

Versuchs mal mit:

Delphi-Quelltext
1:
2:
3:
  DM.JPQuery.SQL.Text :=('Select * From JP Where NOT (Archiv = (' + #39 + 'JA' + #39 + ') 
    OR Papierk = ('
 + #39 + 'JA' + #39 + ') 
    OR Vermittelt = ('
 + #39 + 'JA' + #39 + ')) order by Name');


Zu beachten funktioniert nur wenn es in einer Zeile steht ansonsten noch ein paar '+ usw. hinzufügen ^^


Arne Danikowski - Do 29.04.10 09:43

An der SQL Abfrage:

Delphi-Quelltext
1:
DM.JPQuery.SQL.Text := ('Select * From JP Where NOT (Archiv = (''JA'') OR Papierk = (''JA'') OR Vermittelt = (''JA'')) order by Name');                    


liegt es ja nicht. diese funktioniert und setz nur den Standardfilter wieder ein.

Es liegt an der Abfrage, die mit den Stringwerten der Prozedur


Delphi-Quelltext
1:
procedure TJP_Main.Datenloeschen(Wert, Feld: string);                    


zusammengesetzt wird.


Robert.Wachtel - Do 29.04.10 09:52

user profile iconArne Danikowski hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
[...]
    DM.JPQuery.SQL.Text := 'SELECT * FROM JP WHERE ' + feld + '=' +wert;
[...]

Ein wunderbares Beispiel, warum man doch bitteschön immer parametrisierte Queries einsetzen sollte.

Das wird mit den von Dir übergebenen Werten zu:


SQL-Anweisung
1:
SELECT * FROM JP WHERE papierk = JA                    

Na, fällt Dir was auf?


Arne Danikowski - Do 29.04.10 10:01

Ja aber irgendwie steh ich auf den Schlau, aber wie bekomm ich das nun hin?


Robert.Wachtel - Do 29.04.10 10:08

user profile iconArne Danikowski hat folgendes geschrieben Zum zitierten Posting springen:
Ja aber irgendwie steh ich auf den Schlau, aber wie bekomm ich das nun hin?

Das Stichwort "Parametrisierung" habe ich ja schon genannt.

Oder Du sorgst dafür, dass der wert in Anführungsstrichen steht - aber http://xkcd.com/327/


zuma - Do 29.04.10 10:13

Warum wird das löschen so umständlich gemacht ??
eine simple function könnte das doch so lösen (und zurückgeben, ob gelöscht wurde)


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
function Datenloeschen(xTabelle, xFeld, xWert : String) : boolean;
const
  cLoeschSql = 'Delete from %s where %s = ''%s''';
  cLeseSql   = 'Select * from %s where %s = ''%s''';
begin
  Result := False;
  DM.JpQuery.Sql.Add(Format(cLoeschSql, [xTabelle, xFeld, xWert]); // Löschbefehl aufbereiten
  DM.JPQuery.Open; // Löschen
  DM.JPQuery.Sql.Clear; 
  DM.JPQuery.Sql.Add(Format(cLeseSql, [xTabelle, xFeld, xWert]); // Lesebefehl aufbereiten
  DM.JPQuery.Open;
  Result := DM.JPQuery.Bof and DM.JPQuery.Eof; // Rückgabe, ob Lesebefehl leere Datenmenge ergeben hat
end;


Robert.Wachtel - Do 29.04.10 10:22

user profile iconzuma hat folgendes geschrieben Zum zitierten Posting springen:
Warum wird das löschen so umständlich gemacht ?? [...]

Klassischer Fall vom Austreiben des Teufels mit dem Beelzebub... :mrgreen:


zuma - Do 29.04.10 10:36

user profile iconRobert.Wachtel hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconzuma hat folgendes geschrieben Zum zitierten Posting springen:
Warum wird das löschen so umständlich gemacht ?? [...]

Klassischer Fall vom Austreiben des Teufels mit dem Beelzebub... :mrgreen:


Auf den Streit 'Sql nur mit Parameter Ja/Nein' will ich mich gar nicht einlassen, nutze seit jahren beide Varianten und kann für beide Varianten Vor- und Nachteile benennen, so das ich kein 'So und nicht anders' verfechten möchte.
Parameter sind schon gut und richtig, aber nicht immer die beste Wahl (meistens, aber eben nicht immer).
Hier hab ich das der Einfachheit wegen als Lösung vorgeschlagen.


Robert.Wachtel - Do 29.04.10 10:40

user profile iconzuma hat folgendes geschrieben Zum zitierten Posting springen:
[...] Auf den Streit 'Sql nur mit Parameter Ja/Nein' will ich mich gar nicht einlassen [...]

Mal abgesehen davon, dass ich das nicht meinte, solltest Du Dir vielleicht noch einmal das Begehr des OP genau zu Gemüte führen, bevor Du Deinen Vorschlag so leichtfertig als

Zitat:
[...] Lösung [...]

bezeichnest.


zuma - Do 29.04.10 11:08

user profile iconRobert.Wachtel hat folgendes geschrieben Zum zitierten Posting springen:

Mal abgesehen davon, dass ich das nicht meinte, solltest Du Dir vielleicht noch einmal das Begehr des OP genau zu Gemüte führen ...


Sein 'Begehr' war für mich:
user profile iconArne Danikowski hat folgendes geschrieben Zum zitierten Posting springen:

Es sollen alle Datensätze gelöscht werden, die in der Tabelle "PAPIEK" den Wert 'JA' enthalten:


Robert.Wachtel - Do 29.04.10 11:09

Eine Übererfüllung kann genauso fehlerhaft sein.


zuma - Do 29.04.10 11:16

Da sich das hier gerade in Richtung Offtopic entwickelt, schlag ich vor, wir lassen das mal einfach so stehen, Arne wird sich schon SEINE Lösung erarbeiten oder eben erneut genauer nachfragen.


Robert.Wachtel - Do 29.04.10 11:18

user profile iconzuma hat folgendes geschrieben Zum zitierten Posting springen:
[...] Arne wird sich schon SEINE Lösung erarbeiten [...]

Genau aus diesem Grund habe ich keine "fertige" "Lösung" gepostet.


Arne Danikowski - Do 29.04.10 13:41

Ich wollte in keinster Weise schon wieder eine Grundsatzdisskusion vom Stapel lassen.
Der Hinweis von Robert hat mich schon auf den richtigen Weg gebracht.

Zu Zuma, ist die Lösung einfacher? An Programmzeilen spare ich da nix.
Welchen Vorteil habe ich durch Deinen Programmcode? Ist der schneller und sicherer?
Ich bin für alle Hinweise dankbar.
Ich stelle den Code gerne um, wenn er mir denn Vorteile bringt.


Ich habe den Parameter jedenfalls in Anführungszeichen gebracht und es funktioniert prima.

Nun habe ich pro Aufruf zum Löschen bestimmter Felder mit bestimmten Feldinhalt nur noch 3 Programmzeilen. Darauf wollte ich hinaus.
Denn das Feld und auch der Inhalt wechselt.

Vielen Dank für Eure Antworten!


zuma - Do 29.04.10 15:28

rein von den zeilen her hab ich 6 zeilen weniger geschrieben ;)
aber ernsthafter:
meine Vorteile sehe ich in:
- brauche keinen Query 'abklappern' (bei großen Datenmengen evtl. wg. Geschwindigkeit interessant), sondern gebe den Befehl 'direkt' an die DB (macht auch evtl. Netzwerklast gringer)
- function (also rückmeldung, ob löschen geklappt hat)
- wechsel Feldname/Wert: in meiner Variante kannst du sowohl Feldname und Inhalt als auch die Tabelle per Parameter angeben, somit also auch für andere Tabellen/Feldnamen/Werte-Kombinationen nutzbar (zb DatenLoeschen('Person', 'PersonNr', 1);, DatenLoeschen('Artikel', 'Artikelnr', 12345);, usw)