Announcement

Collapse
No announcement yet.

Trigger funktioniert nicht

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Trigger funktioniert nicht

    Hallo,
    ich sitze jetzt seit 3 Stunden und das Ding funktioniert immer noch nicht. Ich bekomme permanent die Meldung dass bereits ein Cursor mit dem Namen existiert.

    Getestet habe ich das Ding indem ich den Rumpf rausgenommen habe und da ging es.


    Code:
    set ANSI_NULLS ON
    set QUOTED_IDENTIFIER ON
    GO
    
    ALTER Trigger [dbo].[AngebotAuftrag]
    ON [dbo].[Angebot]
    AFTER INSERT,UPDATE
    
    AS
    -- Variablen deklarieren	
    	DECLARE	@BestelllisteID UNIQUEIDENTIFIER,
    			@DistributorID  UNIQUEIDENTIFIER,
    			@id		   UNIQUEIDENTIFIER,	
    			@ArtikelID UNIQUEIDENTIFIER,
    			@VorgangID UNIQUEIDENTIFIER,
    			@Menge	   NUMERIC(5,2),
    			@VK	   NUMERIC(7,2),
    			@EK	   NUMERIC(7,2),
    			@Marge NUMERIC(5,2),
    			@email VARCHAR(512),
    			@KundenID  UNIQUEIDENTIFIER,
    			@Liefertermin DATETIME
    
    	DECLARE Angebot_Art CURSOR FOR
    		SELECT A.Artikelnummer, A.Menge, A.VK_Preis
    		FROM Angebot_Artikel A JOIN Angebot B ON B.id = A.Angebotnummer
    		WHERE A.Angebotnummer = (SELECT id FROM Inserted)
    
    IF EXISTS(SELECT angenommen FROM INSERTED WHERE angenommen = 'True')
    	BEGIN
    			-- bestelle alle noch nicht bestellten Artikel
    			OPEN Angebot_Art
    		
    			FETCH FIRST FROM Angebot_Art
    			INTO @ArtikelID, @Menge, @VK
    			
    			PRINT @ArtikelID
    	
    	WHILE @@FETCH_STATUS  = 0
    		BEGIN
    			-- wenn ArtikelID  auf Bestellliste --> nicht genug da, also Bestellvorschlagmenge um @Menge vergrößern!
    			IF EXISTS(Select ArtikelID FROM Bestellliste WHERE ArtikelID = @ArtikelID)
    				BEGIN
    					PRINT 'Artikel auf  Bestellliste'
    						-- Menge hinzufügen
    					UPDATE Bestellliste SET Menge = ((SELECT Menge 
    													   FROM Bestellliste 
    													  WHERE ArtikelID = @ArtikelID)+@Menge) 
    										   WHERE ArtikelID = @ArtikelID
    				END
    			ELSE
    				BEGIN
    					-- sonst schaue im Artikel nach ob nicht genug auf lager sind bzw. Bestellung nicht ausreicht
    					IF @Menge > (SELECT (Bestand+Bestellt) FROM Artikel WHERE  id= @ArtikelID)
    						BEGIN
    							PRINT 'weniger da als benötigt'
    							SELECT @EK = EK_Preis, @VK = VK_Preis, @Menge = (Bestand+Bestellt)-(Minimum+@Menge) FROM Artikel WHERE id  = @ArtikelID
    							
    								INSERT INTO Bestellliste  (ArtikelID, Menge, VK, EK, Datum)
    									VALUES (@ArtikelID ,@Menge*(-1),  @VK,  @EK ,GETDATE())
    						END
    						-- sonst tue Nichts
    				END
    			-- wenn Menge verändert wurde so trage Menge um 
    		FETCH NEXT FROM Angebot_Art
    		INTO @ArtikelID, @Menge, @VK
    		END
    		
    		CLOSE Angebot_Art
    		DEALLOCATE Angebot_Art
    
    		
    		SELECT @id = id, @VorgangID = VorgangID, @KundenID = KundenID FROM ANgebot where id = '5CA9D67C-7B47-4A67-8DD9-D89485A7ADCA'
    		SELECT @Liefertermin = DATEADD(week,3,GETDATE())
    		INSERT INTO Auftrag(id,VorgangID,Datum,Liefertermin,KundenID) VALUES (@id,@VorgangID,GETDATE(),@Liefertermin,@KundenID)
    			
    		--in Tabelle Auftrag_Artikel einfügen
    			
    		INSERT INTO Auftrag_Artikel (id,AuftragID,ArtikelID,VK_Preis,EK_Preis,Marge,Menge) 
    		SELECT id,Angebotnummer,Artikelnummer,EK_Preis,VK_Preis,Marge,Menge FROM  Angebot_Artikel WHERE angebotnummer = @id
    		
    	END
    Es wäre sehr nett wenn mal jemand drüberschauen könnte.

    Danke

  • #2
    Hallo,

    nach kurzem Überfliegen sieht für mich sehr verdächtig aus, dass Du den Cursor zwar immer definierst, aber nur dann wieder freigibst, wenn die Bedingung

    IF EXISTS(SELECT angenommen FROM INSERTED WHERE angenommen = 'True')...

    erfüllt wird. Man kann auch den Cursor als LOCAL deklarieren, dann ist die Gefahr noch etwas kleiner - oder noch viel besser - man nimmt gar keinen Cursor, weil Cursor ist meisten bäh. Auch in Deinem Fall würde ich mal einschätzen, dass Du mit ein paar temporären Tabellen das Ganze viel eleganter lösen könntest - und ich denke auch performanter bei der Ausführung!

    Hoffentlich war der Hinweis brauchbar.

    Gruß
    Olaf

    Comment


    • #3
      Hallo,
      danke für den Hinweis, ich habe auch schon den Gedanken gehabt, dachte mir aber dass ich durch die FETCH Bedingung des CURSORS jede Zeile einzeln ausgeben lassen zu können wäre ein Vorteil. Ich versuchs mal mit dem LOCAL Cursor.

      Wie stark sind die Performanzgewinne temp table <-> Cursor?
      Ich meine der cursor benutzt ja auch eine temp table. Also mach ich im Prinzip die selben Schritte...

      Comment


      • #4
        UPDATE:
        Ich habe deine Anmerkung befolgt und den Trigger nach der IF schleife deallokiert und am Ende der IF Schleife (sobald keine werte mehr gefetched werden) geschlossen. Das funktioniert aber ich hab ein neues Problem:

        FEHLER 512 .... Zeile 29: Die Unterabfrage hat mehr als einen Wert zurückgegeben. Das ist ungültig wenn die Unterabfrage nach =, <=, >=, .... oder als Ausdruck verwendet wird.

        Das ist komisch, denn die Unterabfragen können diese Bedingung nicht verletzen, da immer nur genau eine Zeile verändert wird (liegt am System welches auf der DB operiert). Ich finde es nicht, habs schon mit X PRINTF Ausgaben probiert, es scheint so als ob es nach dem open für den cursor beginnt, davor funktioniert alles.

        Anstatt einem scroll cursor benutze ich einen normalen und FETCH FIRST = FETCH NEXT bei mir.

        Ideen ?

        Comment


        • #5
          Hallo,

          der Leistungsgewinn beim Verzicht auf SQL-Server Cursor kann wirklich beträchtlich sein. Der ist nun mal absolut auf Mengenoperationen optimiert, was durch den Cursor quasi künstlich ausgebremst wird. Das ist u.U. erst einmal ein Umdenken, aber praktisch immer besser. Ein Cursor ist manchmal auch sinnvoll, ja sogar auch notwendig, aber wenn man ihn vermeiden kann, dann sollte man das auch.

          Gruß
          Olaf

          Comment


          • #6
            ok habe umgeschrieben und siehe da 1. versuch -> funktioniert.

            Danke für den Support Olaf

            Comment

            Working...
            X