Announcement

Collapse
No announcement yet.

Anwendung eines Nested Cursor

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

  • Anwendung eines Nested Cursor

    Hallo zusammen,

    bevor ich den Code poste, der nicht will, was ich will, beschreibe ich mein Problem:

    Ich habe zwei Tabellen. Eine Tabelle (1) mit Bewegungsdaten und eine Tabelle (2) mit Zuordnungsdaten

    In (1) habe ich (u.a.) folgende Columns:

    - Kundennummer
    - Kundenposition
    - Absatz
    - Abgang_Jahr
    - Abgang_Monat

    Die Datensätze sehen wie folgt aus:

    Kunde 4711 Pos 1 Absatz 1000 Abgang NULL
    Kunde 4712 Pos 1 Absatz 500 Abgang NULL
    Kunde 9999 Pos 1 Absatz - ABGANG 2010/04

    Kunde 9999 ist ein Lager, Kunde 4711 und 4712 ein Endkunde. Abgangsdatum steht nur am Lager, nicht am Endkunden. Ich will nun aber wissen, welcher Absatz durch welches abgehende Lager weggebrochen ist

    In (2) steht drin, welches Lager zu welchem Kunden gehört. Bsp.:

    Kunde 4711 Pos 1 Lager 9999 Pos 1
    Kunde 4712 Pos 1 Lager 9999 Pos 1

    etc

    Ich möchte nun das Abgangsdatum des Lagers via UPDATE an den entsprechenden Kundendatensatz des Endkunden einfügen.

    Mein Ansatz wäre ein Cursor, der folgendes macht:

    a) Suche alle Lager mit Abgang in (1)
    b) Schau nach in (2) welche Kunden dazu gehören
    c) Aktualisiere diese Kunden in (1) mit dem Abgangsdatum des Lagers

    Folgenden Code habe ich benutzt, aber er will nicht. (Hintergrund: Ich habe 7 Jahre keinen Cursor mehr geschrieben und grad fachlich etwas ratlos)

    Code:
    DECLARE @dbname VARCHAR(50) 
    DECLARE @Kundennummer VARCHAR(256) 
    DECLARE @Position VARCHAR(256)
    DECLARE @Endkunde VARCHAR(256)
    DECLARE @EndkundePos VARCHAR(256)
    DECLARE @ABGANGSJAHR VARCHAR(4)
    DECLARE @ABGANGSMONAT VARCHAR(2)
    
    DECLARE db_cursor CURSOR FOR 
    
    SELECT     KUNDENNUMMER, KUNDENPOSITION, ABGANG_JAHR, ABGANG_MONAT
    FROM         Sparten.FACT_AutogasZugangAbgang
    WHERE     (SPARTE LIKE '%Agentur%') AND (ABGANG_JAHR <> '') AND (ABGANG_MONAT <> '')
    
    OPEN db_cursor  
    FETCH NEXT FROM db_cursor INTO @KUNDENNUMMER, @Position,@ABGANGSJAHR, @ABGANGSMONAT
    
    WHILE @@FETCH_STATUS = 0  
    BEGIN  
           SELECT KdNr, Pos
           FROM Sparten.DIM_Kunde_Zentralversorger
    	   WHERE ZVersNR = @KUNDENNUMMER 
           AND ZVersPos = @Position
    
           SET @Endkunde = KdNr
    	   SET @EndkundePos = Pos
           
           EXEC sp_AktualisiereKundeMitZentralversorgerAbgangsdatum @Endkunde, @EndkundePos,@ABGANGSJAHR, @ABGANGSMONAT
    
           FETCH NEXT FROM db_cursor INTO @KUNDENNUMMER, @Position,@ABGANGSJAHR, @ABGANGSMONAT  
    END  
    
    CLOSE db_cursor  
    DEALLOCATE db_cursor
    Gespeicherte Prozedur:

    Code:
    CREATE PROCEDURE sp_AktualisiereKundeMitZentralversorgerAbgangsdatum 
    
    	@Endkunde varchar(256),
        @EndkundePos varchar(256),
        @ABGANGSJAHR varchar (4),
        @ABGANGSMONAT varchar (2)
    
    AS
    BEGIN
    	SET NOCOUNT ON;
    
        UPDATE Sparten.FACT_AutogasZugangAbgang
        SET ABGANG_JAHR = @ABGANGSJAHR, ABGANG_MONAT = @ABGANGSMONAT
    	WHERE KUNDENNUMMER = @Endkunde AND KUNDENPOSITION = @EndkundePos
    
    
    END
    Ich bitte um Hilfe und danke im Voraus!

  • #2
    Ein zweiter Versuch sah so aus, der scheint auch halbwegs das richtige zu tun, steigt aber am Ende mit dieser Fehlermeldung aus.

    Code:
    Meldung 16915, Ebene 16, Status 1, Zeile 27
    Ein Cursor mit dem Namen 'inner_cursor' ist bereits vorhanden.
    Meldung 16905, Ebene 16, Status 1, Zeile 32
    Der Cursor ist bereits geöffnet.
    Meldung 16924, Ebene 16, Status 1, Zeile 33
    Cursor-FETCH: Die in der INTO-Liste deklarierte Anzahl von Variablen muss mit der Anzahl der ausgewählten Spalten übereinstimmen.
    Ist die Systemvariable des FETCH_STATUS das Problem?



    [HIGHLIGHT="SQL"]
    --DECLARE @dbname VARCHAR(50)
    DECLARE @Kundennummer VARCHAR(256)
    DECLARE @Position VARCHAR(256)
    DECLARE @Endkunde VARCHAR(256)
    DECLARE @EndkundePos VARCHAR(256)
    DECLARE @ABGANGSJAHR VARCHAR(4)
    DECLARE @ABGANGSMONAT VARCHAR(2)

    DECLARE @fetchdummy VARCHAR(1)



    DECLARE db_cursor CURSOR FOR

    SELECT KUNDENNUMMER, KUNDENPOSITION, ABGANG_JAHR, ABGANG_MONAT
    FROM Sparten.FACT_AutogasZugangAbgang
    WHERE (SPARTE LIKE '%Agentur%') AND (ABGANG_JAHR <> '') AND (ABGANG_MONAT <> '')

    OPEN db_cursor
    FETCH NEXT FROM db_cursor INTO @KUNDENNUMMER, @Position,@ABGANGSJAHR, @ABGANGSMONAT

    WHILE @@FETCH_STATUS = 0
    BEGIN

    DECLARE inner_cursor CURSOR FOR

    SELECT KdNr, Pos
    FROM Sparten.DIM_Kunde_Zentralversorger
    WHERE ZVersNR = @KUNDENNUMMER
    AND ZVersPos = @Position

    OPEN inner_cursor
    FETCH NEXT FROM inner_cursor INTO @Endkunde, @EndkundePos

    WHILE @@FETCH_STATUS = 0

    BEGIN

    UPDATE Sparten.FACT_AutogasZugangAbgang
    SET ABGANG_JAHR = @ABGANGSJAHR, ABGANG_MONAT = @ABGANGSMONAT
    WHERE KUNDENNUMMER = @Endkunde AND KUNDENPOSITION = @EndkundePos

    FETCH NEXT FROM inner_cursor INTO @Endkunde, @EndkundePos
    END

    CLOSE inner_cursor
    DEALLOCATE inner_cursor

    FETCH NEXT FROM db_cursor INTO @KUNDENNUMMER, @Position,@ABGANGSJAHR, @ABGANGSMONAT
    END

    CLOSE db_cursor
    DEALLOCATE db_cursor
    [/HIGHLIGHT]


    Edit: Seltsamerweise bringt jeder anfolgende Lauf nicht das Problem
    Zuletzt editiert von Ishtal; 09.08.2010, 14:29.

    Comment


    • #3
      Also eigentlich sieht das ja ganz gut aus - besteht der Fehler immer noch?
      Wenn ja, würde ich mal ein paar select ... oder print ... zwischendurch einbauen, damit man sieht, wie weit man kommt.
      Oder zusätzlich SQL 2008 Express auf dem Rechner montieren, Datenbank plus procedures rüberkopieren und dort durchdebuggen - der Debugger ist ja ab 2008 wieder fix im ManagementStudio, sogar in der Express-Version

      bye,
      Helmut

      Comment


      • #4
        Ich habe etwas Sorge, dass der Fetch_Status des inneren cursors den des äusseren beeinflusst und der Code daher zu früh aussteigt

        Comment


        • #5
          Ich glaube nicht, dass das mit der Fehlermeldung zu tun hat. Nach der wird irgendwo vorher bereits ein Cursor mit demselben Namen geöffnet, der aber eine andere Anzahl an Feldern hat. Kann es sein, dass diese Prozedur von einer anderen Prozedur aufgerufen wird, in der ebenfalls mit einem Cursor namens 'inner_cursor' gearbeitet wird?

          bye,
          Helmut

          Comment


          • #6
            Nein, das Ganze wird, so wie es ist, als Step in einem SSIS aufgerufen und macht da auch keine Probleme mehr. Obige Fehlermeldung hatte ich nur beim allerersten Mal aus Management Console aufkommen. Vielleicht war da speicherintern noch nicht alles gelöscht?

            Auf jeden Fall scheint es zu laufen, braucht natürlich deutlich Laufzeit (50.000 Datensätze in (1) = > ca 2 mins Laufzeit)

            Zeit ist nicht kritisch bei dieser Datenermittlung, daher stört es mich nicht. Aber welche Chance hätte ich, das Skript perfomanter zu machen? Den Update-Prozess in eine stored procedure auszulagern bringt meiner Meinung nach wenig.

            Andere Ideen?
            Zuletzt editiert von Ishtal; 10.08.2010, 08:17.

            Comment


            • #7
              Andere Frage - ich will das ganze etwas in Sachen Perfomance aufbessern.

              Äusserer Cursor FAST_FORWARD, innerer Cursor FORWARD_ONLY würde ich sagen, oder?

              Comment

              Working...
              X