Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi INSERT INTO sonst UPDATE! (https://www.delphipraxis.net/44175-insert-into-sonst-update.html)

Peeters 14. Apr 2005 17:52

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.

Hansa 14. Apr 2005 18:17

Re: INSERT INTO sonst UPDATE!
 
geht wohl nur mit einer Stored Procedure und einer Variablen da drin

MarcusB 14. Apr 2005 19:05

Re: INSERT INTO sonst UPDATE!
 
Hi,

suchst Du sowas wie REPLACE?

[edit]: Ok, wer lesen kann ist klar im Vorteil, hatte leider MySQL gelesen statt MS SQL :? [/edit]

jensw_2000 14. Apr 2005 19:45

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

Hansa 14. Apr 2005 20:16

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
^

Peeters 15. Apr 2005 16:44

Re: INSERT INTO sonst UPDATE!
 
Wie aber erstelle ich eine SP aus Delphi heraus?

Hansa 15. Apr 2005 16:56

Re: INSERT INTO sonst UPDATE!
 
Wozu so was in Delphi machen ?

Peeters 15. Apr 2005 16:59

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.

Peeters 15. Apr 2005 17:08

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.

Hansa 15. Apr 2005 17:13

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:

Peeters 15. Apr 2005 17:34

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.

Hansa 15. Apr 2005 17:50

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.

Peeters 15. Apr 2005 17:54

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?

Hansa 15. Apr 2005 18:27

Re: INSERT INTO sonst UPDATE!
 
Zitat:

Zitat von Peeters
..ich Sie dort rein ohne Hilfsmittel wie SQL Query Analyzer?

Sage doch der Datenbank, daß der Editor sie heute noch kurz vorbei bringt. :lol:

Robert_G 15. Apr 2005 18:39

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. ;)

jensw_2000 15. Apr 2005 19:19

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:
  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
Den SQL Code kannst du bequem über TAdoCommand an den MSSQL schicken.
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:

Peeters 18. Apr 2005 17:47

Re: INSERT INTO sonst UPDATE!
 
Delphi-Quellcode:
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
Habe mal diese kleine SP geschrieben. Frage dazu, warum gibt er mir keine Datensätze raus? Bei beiden Varianten gibt es min. einen Datensatz.

P.S.: Welches Buch könnt Ihr empfehlen in bezug auf Delphi, ADO und MS-SQL?

jensw_2000 18. Apr 2005 19:51

Re: INSERT INTO sonst UPDATE!
 
Hast du deine SP schon mal in einem SQL Editor (Query Analyzer, OSQL o.Ä) ausprobiert ?
SQL-Code:
  EXEC SP_IMPORT_FORM @FormNr= '1234'
  GO
Kommen dann die gewünschten Daten ?

- 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:

Peeters 18. Apr 2005 22:13

Re: INSERT INTO sonst UPDATE!
 
Ich habe das mit einen DBGrid an Datasource und das an ADOSP gehangen. Mit

Delphi-Quellcode:
CREATE PROCEDURE SP_IMPORT_FORM
AS
SELECT * FROM MPK_FORM
GO
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.

jensw_2000 18. Apr 2005 22:55

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;

Peeters 19. Apr 2005 19:28

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

jensw_2000 19. Apr 2005 22:09

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:
  @FormNr INT = NULL
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 ...

:hi:

Peeters 20. Apr 2005 16:41

Re: INSERT INTO sonst UPDATE!
 
Ich habs, ich depp, habe nicht daran gedacht das @FormNr VARCHAR ist. Jetzt geht es.
Delphi-Quellcode:
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
Langsam steige ich dahinter. Mal schauen wie es weiter geht.

tyron78 18. Okt 2005 23:24

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:
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
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.
Diese Procedure rufe ich in Delphi in einer Funktion wie folgt auf:

Delphi-Quellcode:
  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;
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?

mfg

Ty

Hansa 19. Okt 2005 00:11

Re: INSERT INTO sonst UPDATE!
 
wie wärs hiermit ?
into :par_found;

tyron78 19. Okt 2005 21:43

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...

tyron78 20. Okt 2005 06:42

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:

marabu 20. Okt 2005 07:40

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:
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
Grüße vom marabu

tyron78 20. Okt 2005 08:04

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

tyron78 20. Okt 2005 16:29

Re: INSERT INTO sonst UPDATE!
 
AAAARGHS: So etwas triviales! Das ganze hätte schon wesentlich früher richtig gefunzt, wenn ich nicht

SQL-Code:
 where parameter_id = :pi_parameter_id;
sondern

SQL-Code:
 where upper(parameter_id) = upper(:pi_parameter_id);
geschrieben hätte... im IBExpert hatte ich wohl zufällig die ID groß eingegeben...

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