![]() |
Insert SQL
Hi,
ich komme mit dem insert einfach nicht klar. Um überhaupt etwas in der DB sehen zu können habe ich kurzerhand folgendes probiert:
Code:
Da scheint aber fast alles verkehrt zu sein. 8) Aber es kommt keine Fehlermeldung. Für die ID habe ich einen Trigger, würde das so gehen ?
DS.Close;
DS.UpdateSQL.Text := 'INSERT INTO LAGER (MENGE) VALUES (11)'; DS.Open; |
Wenn Du mit TUpdateSQL ein INSERT-Statement an dei DB schicken willst, dann mußt Du das Statement in die Eigenschaft InsertSQL eintragen.
|
Der Code geht so schon, auch der Trigger feuert, aber im Delphi Programm geht es nicht. Ist das Dataset vielleicht verkehrt ? Aber ich setze doch nur den DB-Befehl damit ab, so wie mit ohne Delphi auch. Mich stört, daß keine Fehlermeldung kommt und sich nichts tut.
|
Hi Hansa,
Zitat:
1. Durch ein Open werden die Update, Refresh, Insert und Delete-Statements der DataSet NICHT ausgeführt, sondern nur durch die entsprechende Methode (.Update, .???, .Insert, .Delete). 2. steht das Ding im Update-SQL drin, so dass zum Ausführen ein Update notwendig währe (funktionieren sollte es aber dann). Wenn Du so was machen willst (ein DML-Statement ausführen ohne vorher eine Datenmenge zu holen) dann schreib das SQL in die normale SelectSQL Eigenschaft rein und führe die SQL dann mit einem ExecSQL aus (nicht Open verwenden!). Grüße Lemmy |
Zitat:
Code:
LagDS.Close;
LagDS.InsertSQL.Text := 'INSERT INTO LAGER (MENGE) VALUES (33)' LagDS.Open; Transaction.Commit; |
Jedes TQuery (und auch dessen Nachkommen in Fremdkomponenten) besitzt die Methode ExecSQL. Diese verwendest Du für Datenmanipulationsabfragen, also INSERT, UPDATE und DELETE, welche keine Datenmenge als Ergebnis zurückliefern.
Delphi-Quellcode:
Damit wird die SQL-Abfrage ausgeführt. Für SELECT-Anweisungen musst Du dagegen open verwenden, um danach auf die zurückgelieferten Daten zugreifen zu können.
DS.SQL.Text := 'INSERT INTO LAGER (MENGE) VALUES (33)';
DS.ExecSQL; ... Ein explizites Schließen des Datasets ist nicht nötig, dies wird beim Zuweisen eines neuen SQL-Befehls automatisch erledigt. :coder: |
Ich muß also TQuery statt Tdataset verwenden ? Probiere es sofort aus, aber was ist bei dem Lagerbeispiel ? Angenommen ich habe einen neuen Artikel, dann ist sowieso keine Datenmenge da, aber bei einem bestehenden Bestand muß ich ja zuerst diesen lesen und dann aktualisieren, z.B. Zugänge verbuchen. Muß ich da jetzt ein Dataset UND ein Query benutzen ? Ersteres zum lesen der vorhandenen Daten und die Query zum updaten, oder wie ?
|
HI Hansa,
nochmal anders: Übliches Vorgehen bei einer TDataSet: 1. Über eine Select-SQL wird eine Datenmenge vom Server geholt:
Code:
2. Über visuelle Felder werden die Daten angezeigt und können bearbeitet werden. Dazu steht z.B. in der DeleteSQL Eigennschaft die entsprechende SQL:
DataSet.SelectSQL.Text:='Select * from Tabelle';
DataSet.Open;
Code:
Diese Standard-SQL-Statements werden bei den entsprechenden Methodenaufrufen (Delete) entsprechend ausgeführt ohne dass der Benutzer noch was machen muss.
delete from Tabelle
where ID = :OLD_ID Für Dein Beispiel würde das heißen:
Code:
Das sind genau die SQL-Statements die z.B. die TIBDataset automatisch generiert (Rechter Mausklick auf die TDataSet). Nun kannst Du mit folgendem Code Inserts durchführen:
LagDS.Close
LagDs.SelectSQL.Text:='Select * from Lager;'; LagDs.DeleteSQL:Text:='Delete from Lager where ????'; LagDs.UpdateSQL.Text:='Update Lager Set.....'; ÖagDs.RefreshSQL.Text:='.....'; LagDs.InsertSQL.Text:='Insert into Lager (Menge) VALUES (:Menge)';
Code:
Du siehst das ist ein riesen Aufwand, speziell dann, wenn man eigentlich keine Daten vom Server holen will. Deshalb gehe ich in diesen Fällen her und verwende direkt die TDataSet.SelectSQL-Eigenschaft, schreibe da die entsprechende SQL rein und führe diese über ein ExecSQL aus, so wie ich es im vorherigen Post geschrieben habe.
LagDS.Open;
LagDS.Insert; LagDS['Menge']:=33; LagDs.Post; LagDS.Close; Transaction.Commit; Grüße Lemmy |
Zitat:
|
Wie kommen die 20 neuen Teile in das "lager"? Durch die explizite Eingabe eines Users in einer Maske oder durch "automatische" Eingabe z.B. bei der Eingabe einer Rechnung?
Im ersten Fall wirst Du doch sowieso die Daten des Lagers irgendwie in einer Tabelle anzeigen lassen, d.h. du hast schon eine TDataSet in Verwendung, die Du dann auch für die Neueingabe verwenden kannst. Im zweite Fall würde ich es über eine spezielle TDataSet/TQuery machen, in der du das Insert eben in die SelectSQL-Eigenschaft schreibst... Grüße Lemmy |
Zitat:
|
Zitat:
Wenn also ein neuer Artikel angelegt wird, wird ersteinmal der Lagerbestand auf 0 gesetzt. Wenn nun dieser Artikel im Wareneingang gebucht wird : - erzeugst Du in deiner Lagerwebewegung-Tabelle einen Eintrag mit den Daten - Änderst Du (wenn Du es denn möchtest) den Bestand in der Tabelle deiner Artikel. |
Hi,
wir posten aneinander vorbei! Nochmal anders: Du musst doch irgendwo eingeben welche Artikel in Deinem Lager sind, oder? Dazu machst Du doch sicherlich ein Formular in dem der User neue Artikel anlegen kann, bzw. bei bestehenden Artikel die Menge editieren kann u. ä. Für dieses Formular wirst Du doch sicherlich eine TDataSet/TIBDataSet/TirgendwasDataSet verwenden um die Daten die schon erfasst sind, anzeigen zu lassen, d.h. Du setzt visuelle DB-Komponenten (TDBEdit, ....) auf das Formular und verbindest das mit der TDataSet. So und jetzt kommen wir wieder zum eigentlichen Thema: In diesem Szenario wirst Du der TDataSet in die SelectSQL-Eigenschaft so eine ähnliche SQL eingeben:
Code:
Mit einem RMK (rechten Mausklick) kannst Du dann (zumindest bei IBX) einen Editor öffnen, in dem Du die Insert, Update, Delete und Refresh-SQL Statements automatisch erzeugen lassen kannst. Dann musst Du nur noch die TDataSet mit der Datenbank verbinden und schon kannst Du loslegen. In Diesem Fall sorgt die TDataSet selbst dafür, dass bei einem Aufruf der Methoden Insert/Edit/Post/Delete die entsprechende SQL die du eingegeben/erzeugt hast ausgeführt wird.
Select * from Lager;
Nun zum großen Unterschied: Wenn du selbst einfach so ein Insert-Statement ausführen willst, ohne eine vorbereitete TDataSet zu haben (wie oben), dann musst Du das entsprechende SQL-Statement auch anders ausführen: entweder in einer TQuery (dann ist eigentlich alles klar) oder eben in einer TDataSet. Dann musst du das Statement eben in die SelectSQL eingeben und dann mittels ExecSQL ausführen. Da spielt es dann keine Rolle was in der Tabelle schon drinsteht, bzw. dass die Eigenschaft des TDataSet "SelectSQL" heißt obwohl Du eine Insert oder Delete-Anweisung eingibst. Denn diese SelectSQL wird bei ExecSQL verwendet und ausgeführt. Grüße Lemmy |
Zitat:
@Lemmy: Deine Frage vorher habe ich nicht sofort verstanden. Es geht um nicht visuelle Sachen. Das soll hinter den Kulissen laufen. |
Zitat:
Ich vermute mal Du meinst folgendes: Das Lager bekommt einen Zugang der Menge x des Artikels y:
|
Zitat:
|
hmm,
du prüfst ja eh mit select ob was da ist da kannst du dass vorhanden ja auch auslesen und dann den zugang addieren und wieder reinschreiben mit Update. Bei leeren Mengen musst du darauf achten ob die DBSpalte NULL sein darf oder auf NOT NULL steht.Achtung '' also ein Leerstring ist nicht NULL.
|
Re: hmm,
Zitat:
|
hmm,
naja wenn halt die Zeile schon da ist recordcount > 0 dann UPDATE, ansonste INSERT
|
Re: hmm,
Zitat:
Code:
nur mal so nebenbei bemerkt. 8) Lemmy hat mich mit seinen leeren Datenmengen trotzdem verwirrt. Lemmy, wo bist Du :?:
IsEmpty
|
Re: hmm,
Zitat:
Wenn Du das kapiert hast, was die anderen so geschrieben haben dann vergiss die leere Datenmenge einfach... Wenn Du es dennoch wissen willst, dann schreib nochmal, nicht dass ich dich noch mehr verwirre.... Grüße Lemmy |
bist hoffentlich nicht beleidigt. Ich mach jetzt einfach notfalls "Try and Error" :mrgreen:
|
Guten Morgen,
Zitat:
Grüße Lemmy |
Re: Insert SQL
Beschäftigt sich derzeit noch jemand mit dem Problem ?
Ich habe auf Grund eurer Beiträge folgenden Code versucht
Delphi-Quellcode:
Die Daten verschwinden auch zunächst im DBGrid.
DM.IBTagesplan.Close;
DM.IBTagesplan.DeleteSQL.Text := 'Delete from UDAT'; //DM.IBTagesplan.InsertSQL.Text := 'Insert Into UDAT (Patient) VALUES (''BlaBla'')'; DM.IBTransaction.Commit; DM.IBTagesplan.Open; Bei Neustart des Programmes sind sie aber wieder vorhanden. Mit
Delphi-Quellcode:
bekomme ich nur die Fehlermeldung "Verwenden Sie Open für eine Select-Anweisung"
DM.IBTagesplan.ExecSql
|
Re: Insert SQL
tausche mal commit und open
|
Re: Insert SQL
es funktioniert einfach nicht:
Mit dieser Anweisung sollte doch eigentlich ein neuer Datensatz eingefügt werden:
Delphi-Quellcode:
DM.IBTagesplan.Close;
DM.IBTagesplan.InsertSQL.Text := 'Insert Into UDAT (ID,UNTERSUCHUNGSDATUM, PATIENT) VALUES (50,''15.10.2005'',''Thomas Cook'')'; DM.IBTagesplan.Open; DM.IBTransaction.Commit; |
Re: Insert SQL
hallo ralf, ich mache soetwas immer mit einer query und zwar so
Delphi-Quellcode:
also ich versuche immer paramisierte felder zu nehmen .versuche es mal auf dein dataset umzusetzen.
with DM1.IBQuery3 do
Begin Close; SQL.Clear; SQL.Add('insert Into Tab_Mitarbeiter (VNummer , Name , Vorname , Beruf , Firmen_Id)'+ 'values (:VNummer,:Name,:Vorname,:Beruf,:Firmen_id)'); ParamByName('VNummer') .AsString := Edit1.Text; ParamByName('Name') .AsString := Edit3.Text; ParamByName('Vorname') .AsString := Edit2.Text; ParamByName('Beruf') .AsString := Edit4.Text; ParamByName('Firmen_Id').AsInteger:= x[ComboBox1.ItemIndex]; Open; end; DM1.IBTrans1.Commit; raik edit :ich hoffe du hast nicht 800*600 als auflösung, bei mir sieht es schrecklich aus |
Re: Insert SQL
Wie kiar das beschrieben hat, so geht es im Prinzip. Wenn schon, dann aber direkt eine stored Procedure verwenden. Ja, man lernt eben nie aus. :zwinker: Das von mir anfangs eingeführte Lager-Beispiel habe ich so realisiert (Menge soll vom Bestand abgezogen werden) :
Delphi :
Delphi-Quellcode:
Voraussetzumg ist natürlich, daß diese SP in der DB definiert ist.
procedure SchreibeLager (menge : integer);
begin with EingDM do begin // EingDM : DataModule LagSP.ParamByName('ID_ART').AsInteger := ArtDS.FieldByName ('ID').AsInteger; ... LagSP.ParamByName('MENGE').AsInteger := menge; LagSP.ExecProc; end; end; DB:
SQL-Code:
Das ist jetzt allerdings noch stark verkürzt. Nicht relevante Felder und Statements habe ich weggelassen.
SET TERM ^ ;
CREATE PROCEDURE LAGSP ( ID_ART INTEGER, MENGE INTEGER) AS DECLARE VARIABLE AENDERN INTEGER; begin AENDERN = -1; SELECT ID FROM LAGER WHERE ID_ART= :ID_ART INTO :AENDERN; IF (AENDERN < 0) THEN BEGIN INSERT INTO LAGER8 (ID_ART,MENGE) VALUES (:ID_ART,-1*:MENGE); END ELSE BEGIN UPDATE LAGER SET MENGE = MENGE - :MENGE WHERE ID_ART = :ID_ART; END suspend; end ^ SET TERM ; ^ Außerdem ist ein guter Trick integriert : nämlich die DB entscheiden zu lassen, ob ein INSERT oder ein UPDATE ausgeführt werden muß. Würde ich auf keinen Fall vernachlässigen :!: Es muß also im Programm nur "SchreibeLager" ausgeführt werden, egal ob der Lagerbestand schon existiert oder nicht !! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:40 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 by Thomas Breitkreuz