![]() |
Datenbank: MS SQL-Server • Version: 2000 • Zugriff über: ADO
INSERT INTO sonst UPDATE!
Hallo,
ich benötige Eure Hilfe. Möchte gerne einen SQL Anweisung erstellen die anhand einer vorhandenen Tabelle abfragt, ob ein vorhandener Datensatz existiert oder nicht, wenn nicht dann INSERT INTO, wenn doch dann UPDATE. Wie ist das am besten zu realisieren? Mit besten Dank im voraus. |
Re: INSERT INTO sonst UPDATE!
geht wohl nur mit einer Stored Procedure und einer Variablen da drin
|
Re: INSERT INTO sonst UPDATE!
Hi,
suchst Du sowas wie ![]() [edit]: Ok, wer lesen kann ist klar im Vorteil, hatte leider MySQL gelesen statt MS SQL :? [/edit] |
Re: INSERT INTO sonst UPDATE!
Am Besten über eine Stored Procedure ...
SQL-Code:
CREATE PROCEDURE SET_Artikel
@SaveOK BIT =0 OUTPUT, -- Ausgabeparameter, mit dem Delphi den Erfolg der SP abfragen kann ... @ArtNr VARCHAR(10) = NULL, @Bezeichnung VARCHAR(50) = NULL, @Preis REAL = 0 AS BEGIN -- Parameter prüfen IF @ArtNr IS NULL OR @Bezeichnung IS NULL BEGIN SELECT @SaveOK=0 RAISERROR('Artielbezeichnung und Artikelnummer dürfen nicht NULL sein ! Vorgang abgebrochen ! ',16,1,'SQL') END ELSE BEGIN -- alle Artikel mit der Artikelnummer "@Artnr" aktualisieren UPDATE Artikel SET Bezeichnung = @Bezeichnung, Preis = @Preis WHERE Artnr = @ArtNr IF @@ROWCOUNT = 0 -- (also kein Datensatz aktualisiert wurde (RowsAffected =0) ) BEGIN INSERT INTO Artikel ( ArtNr, Bezeichnung, Preis ) VALUES ( @ArtNr, @Bezeichnung, @Preis ) END SELECT @SaveOK=1 END END [Zusatz] In Delphi würde ich die SP so benutzen:
Delphi-Quellcode:
Procedure TForm1.Button1Click(Sender:TObject);
begin if SaveArtikel = False then showmessage('Der Datensatz wurde nicht gespeichert'); end; function SaveArtikel:Boolean; var SP:TAdoStoredPoc; begin Result:=False; SP:=TAdoStoredProc.create(nil); try SP.Connection:=Datamodule1.AdoConn; // hier gehören noch ein paar Prüfungen hin SP.Procedurename='SET_Artikel'; // z.B. ist AdoConn.Connected=true ? SP.Parameters.refresh; // enthält edit_Artnr.text einen String, der in SP.Parameters[2].value:=Form1.edit_Artnr.text; // einen Float konvertierbar ist usw ... SP.Parameters[3].value:=Form1.edit_ArtBez.text; SP.Parameters[4].value:=StrToFloat(Form1.edit_ArtPreis.text); SP.ExecProc; Result:=(SP.Parameters[1].value = true); // <<-- das ist SaveOK aus der SP ... finally FreeAndNil(SP); end; end; [/Zusatz] :hi: Schöne Grüße, Jens |
Re: INSERT INTO sonst UPDATE!
Was soll denn die Frage mit Replace zu tun haben ? 8) Ich weiß, was er will. Also : SPs schon mal benutzt ?
So geht das (allerdings in IB/FB) :
SQL-Code:
CREATE PROCEDURE SP (
bla INTEGER, ... ) AS DECLARE VARIABLE AENDERN INTEGER; begin AENDERN = -1; select ID from TABELLE where (.....) into :AENDERN; if (AENDERN < 0) then begin insert into TABELLE (bla,...) values (:bla,...); end else begin update TAG8 set bla=bla+ :bla,... where (???); end suspend; end ^ |
Re: INSERT INTO sonst UPDATE!
Wie aber erstelle ich eine SP aus Delphi heraus?
|
Re: INSERT INTO sonst UPDATE!
Wozu so was in Delphi machen ?
|
Re: INSERT INTO sonst UPDATE!
Weil ich lieber den Ball bei mir halten möchte. Auch bei den Views mache ich das so bzw. ich erstelle aus Delphi heraus immer wieder eine SELECT Anweisung, um Daten auf das Formular zubekommen.
|
Re: INSERT INTO sonst UPDATE!
Der eigenliche Hintergrund ist, ich möchte nicht das der Anwender damit konfrontiert wird erst einmal mit den SQL Query Analyzer die SP zu erstellen. Ich möchte lieber, wenn es dann soweit ist das aus Delphi heraus die SP erstell bzw. gändert wird. Ohne das ich den Analyzer dazu bewegen muss die neue SP einzulesen.
|
Re: INSERT INTO sonst UPDATE!
Du willst also den Anwender eine SP zusammenbauen lassen, obwohl du selber nicht weißt, wie das überhaupt geht ? :shock:
|
Re: INSERT INTO sonst UPDATE!
Nein, so meinte ich das nicht. Der Anwender soll gerade nicht die SP erstellen. Ich möchte in Delphi eine SP programmieren und diese dann an den Server übermitteln. Das Thema SP ist für mich noch neu, ich muss mich also noch zurecht finden bzw. anhand von Beispielen diese ausarbeiten.
|
Re: INSERT INTO sonst UPDATE!
War zu erwarten. 8) Aber ich sage dir gleich : die SP liegt in der Datenbank und nicht in Delphi :!: Also mußt du dich entscheiden, ob du nun einen Nagel mit einem Schraubenzieher (Delphi) in die Wand haust oder mit dem geeigneten Werkzeug.
|
Re: INSERT INTO sonst UPDATE!
Das die SP in der Datenbank liegt ist klar. Nur wie bekomme ich Sie dort rein ohne Hilfsmittel wie SQL Query Analyzer?
|
Re: INSERT INTO sonst UPDATE!
Zitat:
|
Re: INSERT INTO sonst UPDATE!
Hihi, ob ich es noch erlebe, dass jemand Hansas Beiträge versteht? :lol:
@Peeters Was dir Hansa auf seine so direkte und unglaublich unmissverständliche Art ( :mrgreen: ) sagen will, ist, dass du die Prozedur mit einer IDE für deine DB entwickeln solltest. Wenn sie passt kannst du den Code imme noch dynamisch per Delphi absetzen. ;) |
Re: INSERT INTO sonst UPDATE!
Wenn du den Code zum Erstellen der Stored Procedure aus Delphi absetzt, dann solltest du vorder prüfen ob diese eventuell schon in der DB existiert.
Das geht so ...
SQL-Code:
Den SQL Code kannst du bequem über TAdoCommand an den MSSQL schicken.
IF EXISTS (SELECT Name FROM SysObjects
WHERE Name = 'Meine_SP' AND TYPE = 'P') -- P = Stored Procedure ... BEGIN ALTER PROCEDURE ... -- Procedure in DB aktualisieren END ELSE BEGIN CREATE PROCEDURE ... -- Procedure in DB erstellen END Zu beachten ist jedoch, das der User, der diesen Code aus deinem Programm an den SQL-Server sendet, das Recht zum Erstellen, Ändern und Löschen von Datenbankobjekten hat. Jeder darf das nicht ... [Zusatz] Hier noch eine komplette Liste der TYPE Kennungen in SYSOBJECTTS ... Falls mal jemand einen anderen Objekttyp suchen möchte ... Objekttyp. Kann einer der folgenden Objekttypen sein: C = CHECK-Einschränkung D = Standard- oder DEFAULT-Einschränkung F = FOREIGN KEY-Einschränkung L = Protokoll FN = Skalarfunktion IF = Inlinetabellenfunktion P = Gespeicherte Prozedur PK = PRIMARY KEY-Einschränkung (Typ ist K) RF = Gespeicherte Replikationsfilterprozedur S = Systemtabelle TF = Tabellenfunktion TR = Trigger U = Benutzertabelle UQ = UNIQUE-Einschränkung (Typ ist K) V = Sicht X = Erweiterte gespeicherte Prozedur [/Zusatz] :hi: |
Re: INSERT INTO sonst UPDATE!
Delphi-Quellcode:
Habe mal diese kleine SP geschrieben. Frage dazu, warum gibt er mir keine Datensätze raus? Bei beiden Varianten gibt es min. einen Datensatz.
CREATE PROCEDURE SP_IMPORT_FORM
@FormNr VARCHAR(5) = NULL AS IF @FormNr < 10000 BEGIN SELECT * FROM MPK_FORM WHERE FORMNR = @FormNr END ELSE BEGIN SELECT * FROM MPK_PREIS WHERE FORMNR = @FormNr END GO P.S.: Welches Buch könnt Ihr empfehlen in bezug auf Delphi, ADO und MS-SQL? |
Re: INSERT INTO sonst UPDATE!
Hast du deine SP schon mal in einem SQL Editor (Query Analyzer, OSQL o.Ä) ausprobiert ?
SQL-Code:
Kommen dann die gewünschten Daten ?
EXEC SP_IMPORT_FORM @FormNr= '1234'
GO - Wenn ja, nehme ich an, das du dich an meinem obigen Beispiel origentiert hast, um die SP aus Delphi heraus auszuführen ... Im Unterschied zu INSERT oder UPDATE soll die SP jetzt ja Datensätze zurückliefert. Dann musst du anstatt ExecProc "Open" und "Close" verwenden wie bei jedem anderen Dataset, von dem Du eine Result-Datenmenge erwartest, auch ... - Wenn nicht dann teste mal die beiden Select's per Hand aus und schau mal wo es klemmt ... Wirklich gute Bücher habe ich auch noch nicht gefunden. Entweder sind sie zu oberflächlich oder es sind reine Syntax Referenzen. Kapitel wie Optimierung, Troubleshooting usw fehlen oft ganz ... Beim MSSQL kannst du im MSDN recht gute Erklärungen finden oder im Entwicklerforum oder hier in der DP :hi: |
Re: INSERT INTO sonst UPDATE!
Ich habe das mit einen DBGrid an Datasource und das an ADOSP gehangen. Mit
Delphi-Quellcode:
hat er eine Ergebnissmenge angezeigt. Nur jetzt mit der "IF" Variante kommt nichts mehr raus. Am Grid erkenne ich das er wenigstens die Feldnamen ausgelesen hat.
CREATE PROCEDURE SP_IMPORT_FORM
AS SELECT * FROM MPK_FORM GO |
Re: INSERT INTO sonst UPDATE!
Könnte ein Problem bei der Parameterübergabe sein.
Wann und wie füllst du @FormNr mit einen Wert ? Versuch es mal so ...
Delphi-Quellcode:
Procedure TForm1.button1Click(Sender:TObject);
begin ADOSP.Close; ADOSP.Procedurename='SP_IMPORT_FORM '; ADOSP.Parameters.refresh; ADOSP.Parameters[1].value:='EIN_GÜLTEGER_WERT_FÜR_@FORMNR'; ADOSP.Open; end; |
Re: INSERT INTO sonst UPDATE!
Ich habe direkt in den Eigenschaften einen Wert eingetragen um das Verhalten erst einmal zu testen. Ich habe das auch mit einer einfachen SELECT Anweisung ausprobiert, und es kam zu einen Ergebnis.
Delphi-Quellcode:
CREATE PROCEDURE SP_IMPORT_FORM
@FormNr VARCHAR(5) = NULL AS SELECT * FROM MPK_FORM WHERE FORMNR = @FormNr GO |
Re: INSERT INTO sonst UPDATE!
Hm... :gruebel:
ausser das du bei deinem bedingten SELECT den Datentyp (INT) verwendest, aber @FormNr als VARCHAR deklarierst finde ich keine Fehler ...
SQL-Code:
@FormNr VARCHAR(5) = NULL -- hier sollte INT = NULL stehen
AS IF @FormNr < 10000 -- wenn du hier den Parameter gegen eine Integer vergleichst Der MSSQL ist zwar meistens kulant bei unterschiedlichen Datentypen (insofern die Daten richtig interpretiert werden können), aber es ist der letzte offensichtliche Fehler ... Probier doch mal deinen Parameter in der SP anzupassen ...
SQL-Code:
Nachdem du die SP gespeichert hast, musst du deine ADOSP im Delphi disconnecten, neu connecten und die Parameter neu auslesen sonst bekommt ADO nicht mit, das sich die Parameterdeklaration geändert hat ...
@FormNr INT = NULL
:hi: |
Re: INSERT INTO sonst UPDATE!
Ich habs, ich depp, habe nicht daran gedacht das @FormNr VARCHAR ist. Jetzt geht es.
Delphi-Quellcode:
Langsam steige ich dahinter. Mal schauen wie es weiter geht.
CREATE PROCEDURE SP_IMPORT_FORM
@FormNr VARCHAR(5) = NULL AS IF @FormNr = '00475' BEGIN SELECT * FROM MPK_FORM WHERE FORMNR = @FormNr END ELSE BEGIN SELECT * FROM MPK_PREIS WHERE FORMNR = QFormNr END GO |
Re: INSERT INTO sonst UPDATE!
Hallo, liebe DPler.
Bin grad über die Suche auf den thread hier gestoßen, und da mein Problem ein ähnliches ist und ich (mal wieder) etwas festhänge, dachte ich, ich poste mal: Ich greife auf eine Interbase DB zu, in der ich folgende stored procedure habe:
SQL-Code:
Die beiden :PI_ Variablen sind meine Input-Parameter, :PO_ entsprechend der Output-Parameter. par_found ist eine integer-Variable der Procedure. Das ganze hab ich im IB-Expert schon getestet und es scheint auch soweit korrekt zu laufen.
begin
select count(*) from mcsc_parameter where upper(parameter_id) = upper(:pi_parameter_id) into par_found; if (par_found = 0) then insert into mcsc_parameter values (:pi_parameter_id, :pi_parameter_value); else update mcsc_parameter set parameter_value = :pi_parameter_value where parameter_id = :pi_parameter_id; po_ret_val = par_found; suspend; end Diese Procedure rufe ich in Delphi in einer Funktion wie folgt auf:
Delphi-Quellcode:
Rufe ich jetzt (z.B. in einem Button-Pressed Event) diese Funktion mit zwei Parametern auf und laß mir das Ergebnis ausgeben, so erhalte ich erwartungsgemäß das Ergebnis der stored Proc, nämlich die Anzahl der vorhandenen Parameter in der Tabelle, die dem ersten Parameter entsprechen (im Normalfall 0 oder 1). Schaue ich jedoch dann in die DB, wurde weder Update noch Insert ausgeführt (was im IB Expert aber funktioniert hat). Commit kann ich aus der Procedure nicht aufrufen und das Commit der default transaction ändert auch nichts... irgendeine Idee, woran das liegen kann?
function TDataModule2.MCSC_Put_Param_Value(par_id, par_val: string): String;
var par_ind: integer; begin; if par_id = '' then par_id := 'DUMMY'; par_id := Uppercase(par_id); self.MCSC_StoredProc_IB_1.StoredProcName := 'MCSC_PUT_PARAMETER'; par_ind := self.MCSC_StoredProc_IB_1.ParamByName('PI_PARAMETER_ID').Index; self.MCSC_StoredProc_IB_1.Params[par_ind].Value := par_id; par_ind := self.MCSC_StoredProc_IB_1.ParamByName('PI_PARAMETER_VALUE').Index; self.MCSC_StoredProc_IB_1.Params[par_ind].Value := par_val; self.MCSC_StoredProc_IB_1.ExecProc; par_val := self.MCSC_StoredProc_IB_1.Params.ParamValues['PO_RET_VAL']; Result := par_val; end; mfg Ty |
Re: INSERT INTO sonst UPDATE!
wie wärs hiermit ?
into :par_found; |
Re: INSERT INTO sonst UPDATE!
Aber was ändert da das :par_found? Wie gesagt: der Rückgabewert scheint ja korrekt zu sein, aber es wird halt nichts committed, wenn ich die proc aus delphi heraus ausführe...
|
Re: INSERT INTO sonst UPDATE!
Woran kann es denn nun liegen, daß nicht commited wird??? Wie gesagt: im IB-Expert funzt die stored procedure! Nur beim Aufruf über Delphi nicht! :-(( Muß man explizit ein Commit absetzen? Wenn ja, welches? :gruebel: Das Commit der Standard Transaktion hat nichts bewirkt... ich kapiers einfach nich! :wall:
|
Re: INSERT INTO sonst UPDATE!
Nicht, dass ich deinen Code ausprobiert hätte - oder gar meinen - aber müsste er nicht so aussehen?
SQL-Code:
Grüße vom marabu
begin
select count(*) from mcsc_parameter where upper(parameter_id) = upper(:pi_parameter_id) into :po_ret_val; if (po_ret_val = 0) then insert into mcsc_parameter values (:pi_parameter_id, :pi_parameter_value); else update mcsc_parameter set parameter_value = :pi_parameter_value where parameter_id = :pi_parameter_id; suspend; end |
Re: INSERT INTO sonst UPDATE!
Hm... klingt plausibel - werd ich nachher mal ausprobieren. Aber hat das was mit dem Commit bzw. dem Fehlen des selbigen zu tun?
Beispiel: in meiner DB hab einen Parameter dummy mit dem Wert test. Führe ich im IB Expert die Procedure mit den Parametern dummy und test5 aus, steht hinterher in der DB dummy und test5. Starte ich das ganze aus Delphi und schaue danach per IB Expert in die DB steht da immernoch dummy und test |
Re: INSERT INTO sonst UPDATE!
AAAARGHS: So etwas triviales! Das ganze hätte schon wesentlich früher richtig gefunzt, wenn ich nicht
SQL-Code:
sondern
where parameter_id = :pi_parameter_id;
SQL-Code:
geschrieben hätte... im IBExpert hatte ich wohl zufällig die ID groß eingegeben...
where upper(parameter_id) = upper(:pi_parameter_id);
thx trotzdem für alle Tips! Hab auch das Into entsprechend angepaßt... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:33 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