Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   DeleteSQL (https://www.delphipraxis.net/185958-deletesql.html)

Luckner 22. Jul 2015 09:11

Datenbank: Firebird • Version: 1.5 • Zugriff über: Dataset

DeleteSQL
 
Hallo,
habe ein Problem mit der u.g. Routine einige Datensätze in einer Tabelle zu löschen. Die Tabell gibts es, die Felde ebenfalls und die Datensätze auch. Bekommen eine Fehlermeldung "IBDatasetArtikelStanzen: Operation bei leeren Datenmenge nicht ausführbar"

Delphi-Quellcode:
DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;
 DataArtikelStanzen.IBDataSetArtikelStanzen.DeleteSQL.Clear;
 DataArtikelStanzen.IBDataSetArtikelStanzen.DeleteSQL.Text := 'delete from ARTIKELSTANZEN where ARTIKEL_ID = ' +  QuotedStr(IntToStr(selectArtikel));
 DataArtikelStanzen.IBDataSetArtikelStanzen.Open;
 DataArtikelStanzen.IBDataSetArtikelStanzen.Delete;
Was sehe ich hier nicht?
Danke.

Bernhard Geyer 22. Jul 2015 09:20

AW: DeleteSQL
 
Ein .Open liefert eine Ergebnismenge zurück. Wie soll es eine Ergebnismenge bei einem "DELETE ..." geben?

Dafür gibts die Exec(SQL)-Methode wenn man SQL-Statements ohne Ergebnismenge ausführen will.

Luckner 22. Jul 2015 09:37

AW: DeleteSQL
 
Delphi-Quellcode:
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;
 DataArtikelStanzen.IBDataSetArtikelStanzen.DeleteSQL.Clear;
 DataArtikelStanzen.IBDataSetArtikelStanzen.DeleteSQL.Text := 'delete from ARTIKELSTANZEN where ARTIKEL_ID = ' +  QuotedStr(IntToStr(selectArtikel));
 DataArtikelStanzen.IBDataSetArtikelStanzen.ExecSQL;
So bekommen ich die Meldung "Verwenden Sie Open für eine select-Anweisung"

blawen 22. Jul 2015 09:41

AW: DeleteSQL
 
Zitat:

Zitat von Luckner (Beitrag 1309468)
Delphi-Quellcode:
'delete from

Fehlt da nicht was?
Delphi-Quellcode:
delete * from...

Luckner 22. Jul 2015 09:58

AW: DeleteSQL
 
* wird bei delete nicht verwendet. Es wird der gesamter Datensatz gelöscht.

mkinzler 22. Jul 2015 09:58

AW: DeleteSQL
 
Das Statement unter DeleteSQL wird aufgerufen, wenn man ein <DataSet>.Delete durchführt.
Lass Dir dies am Besten in der IDE erstellen, dann wird diese parametrisiert angelegt.

x000x 22. Jul 2015 10:02

AW: DeleteSQL
 
Das Statement denke ich passt schon so... Ich kenne die Komponente nicht, gehe aber davon aus, dass wenn es ein .DeleteSQL gibt, dass es dafür dann auch einen gesonderten Aufruf gibt. Ein .ExecSQL bezieht sich vermutlich auf die Eigenschaft .SQL und nicht auf .DeleteSQL

BadenPower 22. Jul 2015 10:06

AW: DeleteSQL
 
Zitat:

Zitat von Luckner (Beitrag 1309468)
So bekommen ich die Meldung "Verwenden Sie Open für eine select-Anweisung"

Und was steht in der .SelectSQL?

Zitat:

Zitat von Luckner (Beitrag 1309460)
Fehlermeldung "IBDatasetArtikelStanzen: Operation bei leeren Datenmenge nicht ausführbar"

Du bekommst scheinbar durch das .Open eine leere Datenmenge zurückgeliefert.

FBrust 22. Jul 2015 10:12

AW: DeleteSQL
 
Hallo,

Zitat:

DataArtikelStanzen.IBDataSetArtikelStanzen.DeleteS QL.Text := 'delete from ARTIKELSTANZEN where ARTIKEL_ID = ' + QuotedStr(IntToStr(selectArtikel));
ergäbe als Beispiel

delete from ARTIKELSTANZEN where ARTIKEL_ID = '7'


Ist das Feld ARTIKEL_ID ein String-Feld (z. B. varchar)?

Falls nicht, wäre das QuotedStr überflüssig.

Gruß
Frank

mkinzler 22. Jul 2015 10:13

AW: DeleteSQL
 
Zitat:

Zitat von x000x (Beitrag 1309475)
Das Statement denke ich passt schon so...

Zitat:

Nein es stimmt nicht.
Ich kenne die Komponente nicht, gehe aber davon aus, dass wenn es ein .DeleteSQL gibt, dass es dafür dann auch einen gesonderten Aufruf gibt.
Ja <DataSet>.Delete
Zitat:

Ein .ExecSQL bezieht sich vermutlich auf die Eigenschaft .SQL und nicht auf .DeleteSQL
Ja. Wenn man dort ein DML Statement hinterlegt.
Wenn man man mit DataSets arbeitet, führt

.Open das SelectSQL
.Delete das DeleteSQL
usw. aus.

Die Statement müssen entsprechend parametrisiert sein.

p80286 22. Jul 2015 10:14

AW: DeleteSQL
 
Versuch es doch mal so:
Delphi-Quellcode:
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;
 DataArtikelStanzen.IBDatabaseArtikelStanzen.SQL.Text:='delete from Tabelle where id=123456';
 DataArtikelStanzen.IBDatabaseArtikelStanzen.ExecSQL;
// vllt. noch die betroffenen Zeilen auslesen
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;
Gruß
K-H

jobo 22. Jul 2015 10:21

AW: DeleteSQL
 
Zitat:

Zitat von p80286 (Beitrag 1309480)
Versuch es doch mal so:
Delphi-Quellcode:
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;
 DataArtikelStanzen.IBDatabaseArtikelStanzen.SQL.Text:='delete from Tabelle where id=123456';
 DataArtikelStanzen.IBDatabaseArtikelStanzen.ExecSQL;
// vllt. noch die betroffenen Zeilen auslesen
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;

Ich schätze, damit verbiegt man die Datenquelle des Dataset und macht es ~nur noch schlimmer.
MKINZLER hat schon die richtigen Hinweise gegeben. DeleteSQL ist nicht für den manuellen Aufruf gedacht, sondern implementiert die Umsetzung des Dataset.Delete.

Bernhard Geyer 22. Jul 2015 10:32

AW: DeleteSQL
 
Zitat:

Zitat von blawen (Beitrag 1309471)
Zitat:

Zitat von Luckner (Beitrag 1309468)
Delphi-Quellcode:
'delete from

Fehlt da nicht was?
Delphi-Quellcode:
delete * from...

Nö. Nur Pseudodatenbanken wie MS Access verlangen (teilweise) das * bei dieser DML-Anweisung

p80286 22. Jul 2015 10:36

AW: DeleteSQL
 
Zitat:

Zitat von jobo (Beitrag 1309481)
Zitat:

Zitat von p80286 (Beitrag 1309480)
Versuch es doch mal so:
Delphi-Quellcode:
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;
 DataArtikelStanzen.IBDatabaseArtikelStanzen.SQL.Text:='delete from Tabelle where id=123456';
 DataArtikelStanzen.IBDatabaseArtikelStanzen.ExecSQL;
// vllt. noch die betroffenen Zeilen auslesen
 DataArtikelStanzen.IBDatabaseArtikelStanzen.Close;

Ich schätze, damit verbiegt man die Datenquelle des Dataset und macht es ~nur noch schlimmer.
MKINZLER hat schon die richtigen Hinweise gegeben. DeleteSQL ist nicht für den manuellen Aufruf gedacht, sondern implementiert die Umsetzung des Dataset.Delete.

Könntest Du mir das mal erklären?
Nach meinem Verständnis verbirgt sich hinter DataArtikelStanzen.IBDatabaseArtikelStanzen. eine Query und dann sollte das passen, oder hab ich da was in den falschen Hals bekommen?

Gruß
K-H

Luckner 22. Jul 2015 10:58

AW: DeleteSQL
 
Hinter "DataArtikelStanzen.IBDatabaseArtikelStanzen" verbirgt sich ein Dataset. Komisch, ich habe es schon so einigemale benutzt ohne Probleme. Auch ohne dem "where ...". Habe auch für ARTIKEL_ID eine 3 gesetzt, wie in der Tabelle. QuotedStr ist falsch an dieser Stelle (war nur ein Versuch).Immer wieder der selber Fehler.

Hier noch ein Beispiel:
Delphi-Quellcode:
  DataModuleAlternativMaterial.MatZuKunden_Grid.Close;
  DataModuleAlternativMaterial.MatZuKunden_Grid.DeleteSQL.Clear;
  DataModuleAlternativMaterial.MatZuKunden_Grid.DeleteSQL.Text := 'DELETE FROM MATZUKUNDEN WHERE MATERIALID LIKE ' + IntToStr(selectmaterial);
  DataModuleAlternativMaterial.MatZuKunden_Grid.Open;
und es funktioniert.

Delphi-Quellcode:
  DatamodulePlannung.DataModule5.IBDataSetGridPlannung.Close;
  DatamodulePlannung.DataModule5.IBDataSetGridPlannung.DeleteSQL.Clear;
  DatamodulePlannung.DataModule5.IBDataSetGridPlannung.DeleteSQL.Text := 'delete from PLANUNG';
  DatamodulePlannung.DataModule5.IBDataSetGridPlannung.Open;
  DatamodulePlannung.DataModule5.IBDataSetGridPlannung.Delete;
auch das funktioniert.

BadenPower 22. Jul 2015 11:17

AW: DeleteSQL
 
Zitat:

Zitat von Luckner (Beitrag 1309489)
Hinter "DataArtikelStanzen.IBDatabaseArtikelStanzen" verbirgt sich ein Dataset.
...
Immer wieder der selber Fehler.

Hast Du jetzt schon einmal überprüft, od die Datenmenge nach dem .Open überhaupt Datensätze enthält.

Die Fehlermeldung deutet darauf hin, dass die Datenmenge LEER ist und kein Datensatz nach dem .Open vorhanden ist.

Luckner 22. Jul 2015 11:20

AW: DeleteSQL
 
Mit " Label138.Caption := IntToStr(DataArtikelStanzen.IBDataSetArtikelStanze n.RecordCount); stelle ich fest, dass RecordCount = 0 ist, obwohl mindestens 2 Datensätze drin sind. Deshalb ist nichts zu löschen da. Also werde ich mir mal das Dataset anschauen.

Sir Rufo 22. Jul 2015 11:23

AW: DeleteSQL
 
Es ist immer ganz wichtig so wenig Query-Komponenten zu verwenden, wie nur irgend möglich. Am Besten nur eine verwenden, dann hat man das Golden Ring-Anti-Pattern perfekt umgesetzt.
Zitat:

One Query-Component to rule them all.
Dieser Unfug ist tatsächlich sehr verbreitet.

Warum keine
Delphi-Quellcode:
PlanungDeleteQuery
die fix und fertig da ist und ausschließlich zum Löschen von einem Planungsdatensatz vorhanden ist?

Eine Methode davor gebaut
Delphi-Quellcode:
procedure TMyDataModule.DeletePlanung( PlanungID: Integer );
begin
  PlanungDeleteQuery.ParamByName( 'ID' ).Value := PlanungID;
  PlanungDeleteQuery.ExecSQL;
end;
Evtl. viel zu einfach und zu sehr straight forward ...

p80286 22. Jul 2015 11:30

AW: DeleteSQL
 
@Sir Rufo
DRY?
Warum für 50 Fragestellungen 50 Querys definieren wenn 50 x SQLText reicht?

Gruß
K-H

Sir Rufo 22. Jul 2015 11:32

AW: DeleteSQL
 
Zitat:

Zitat von p80286 (Beitrag 1309503)
@Sir Rufo
DRY?
Warum für 50 Fragestellungen 50 Querys definieren wenn 50 x SQLText reicht?

Gruß
K-H

Wegen Prepared Statements => Performance?

Hier haben wir es allerdings mit einem SuperGAU zu tun. Die Query wird zur Anzeige von Daten verwendet und wird dann mal flugs umgebaut. Da kräuseln sich einem die Nackenhaare.

Luckner 22. Jul 2015 11:46

AW: DeleteSQL
 
Danke für die Unterstützung. Habe eine weitere Query eingesetzt (wie Sir Rufo vorgeschlagen hat) und es funktioniert. Denke auch, für solche Aufgaben ist eine weitere Query schon nicht schlecht.

Danke.

frankyboy1974 22. Jul 2015 12:28

AW: DeleteSQL
 
Hallo,

ich möchte hier mal antworten:
:lol:

Ich benutze in meinem eigenem Persistenz-Framework grundsätzlich tatsächlich nur eine Query-Komponente. Ob ich nun ein 'Select' oder ein 'Delete' oder was auch immer gegen die Datenbank huste, spielt erst mal keine Rolle. Delphi-Entwickler benutzen gerne für jede Abfrage ein neues Query-Objekt, eins sollte grundsätzlich reichen, lässt man Nebenläufigkeit jetzt erst mal aus dem Spiel.


mfg

frank

jobo 22. Jul 2015 13:48

AW: DeleteSQL
 
Zitat:

Zitat von frankyboy1974 (Beitrag 1309513)
Ich benutze in meinem eigenem Persistenz-Framework grundsätzlich tatsächlich nur eine Query-Komponente. Ob ich nun ein 'Select' oder ein 'Delete' oder was auch immer gegen die Datenbank huste, spielt erst mal keine Rolle. Delphi-Entwickler benutzen gerne für jede Abfrage ein neues Query-Objekt, eins sollte grundsätzlich reichen, lässt man Nebenläufigkeit jetzt erst mal aus dem Spiel.

Also
1. Benutzt der TE sehr wahrscheinlich nicht Dein Persistenzframework
und
2. haben wir hier die Situation, dass die betreffende Query Teil (property) einer Datasetkomponente ist, die einen speziellen Zweck erfüllen soll.
Summa summarum macht es an der Stelle keinen Sinn, die "Schwesterproperty" für das Dataset zu vergewaltigen und dort das Delete einzutragen und auch nicht unbedingt eine separate Query zu erfinden, die im Delete Fall durchführt, wofür es eine vorgesehene Methode gibt. Standard Code, der per Dataset.Delete arbeitet, dürfte an der Stelle sonst auch nicht funktionieren.

Sir Rufo 22. Jul 2015 14:05

AW: DeleteSQL
 
@frankyboy1974

So gekapselt und von der weiteren Verwendung versteckt kann man das auch ruhig machen.

Hier wurde aber gerade gezeigt, dass ein DataSet, was aktiv für die Anzeige eines Grid zuständig ist auch mal eben flugs für das Absetzen eines Statements missbraucht wird.

Und wenn du dein Framework passend aufgebaut hast
Delphi-Quellcode:
TFramework = class
private
  FGoldenRingQuery : TQuery;
protected
  // Bereitet die Query für den Abfrage-Kontext vor
  function GetQuery( const QueryContext: string ): TQuery;
end;
dann ist es ja auch ein Leichtes, hier ein Dictionary aufzusetzen, was dann für jeden Abfrage-Kontext eine eigene Query-Konponente zur Verfügung stellt und vorhält.

Falls es nämlich mal zu zeitlichen Engpässen kommen sollte (viele Operation mit ständig wechselndem Query-Kontext). Denn bei jedem Zuweisen des SQL-Textes wird dieser immer wieder geparst, um die Parameter herauszufinden. ;)

Neumann 22. Jul 2015 14:21

AW: DeleteSQL
 
Noch mal kurz sortiert:

Das Dataset ist wohl ein IBDataset.

Dies enhält mehrere SQLs für open, insert, update, delete, die aber nicht direkt aufgerufen werden, sondern dann, wenn ein Aufruf der Methode des Datasets erfolgt.
Ist das Dataset nicht offen, kann man nichts davon verwenden (außer natürlich open), Dataset.insert, delete usw. funktionieren nicht.

Will man wie angegeben nur einen Datensatz löschen dann nimmt man eine SQL-Komponente, schreibt das SQL-Kommando in deren SQL-Feld, dann execute und fertig.

Das Dataset ist dann praktisch, wenn man die Daten anzeigen will und der Benutzer Änderungen macht, die über die eingebauten SQL-Befehle ausgeführt werden.

jobo 22. Jul 2015 14:31

AW: DeleteSQL
 
Zitat:

Zitat von Neumann (Beitrag 1309531)
Noch mal kurz sortiert:

Ja genau, ich möchte noch ergänzen:
Will man einen Datensatz löschen, der im (offenen ) Dataset vorliegt, verwendet man dataset.delete.
Will man irgendeinen anderen Datensatz löschen, außerhalb der (offenen) Dataset oder außerhalb des Filterbereichs, dann nimmt man eine separate Query.

Ansonsten halt ein anderes Verfahren, siehe Voryschlag Sir Rufo oder sonst ein konsistentes Framework, aber nicht diesen wirren Mix.

Sir Rufo 22. Jul 2015 14:38

AW: DeleteSQL
 
So sieht das aus.

Und als Ergänzung, wofür diese ganzen SQL Eigenschaften sind hier ein kleines Beispiel:
  • Delphi-Quellcode:
    SQL.Text
    :
    SQL-Code:
    select id, name from foo where deleted=0
  • Delphi-Quellcode:
    DeleteSQL.Text
    :
    SQL-Code:
    update foo set deleted=1 where id=:ID
Nun wird der Datensatz beim Aufruf von
Delphi-Quellcode:
DataSet.Delete;
in der Datenbank nicht wirklich gelöscht, sondern nur als gelöscht markiert und das Abfrage-Statement sorgt dafür, dass die "gelöschten" Daten auch nicht mehr angezeigt werden.

So kann man auch mit dem Navigator/Grid spezielle Löschoperation (oder Update/Insert) durchführen


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:53 Uhr.

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