Ergebnis 1 bis 4 von 4

Thema: Aufruf von Update vor einem Update auf gleiche Tabelle

  1. #1
    Heisp ist offline Neuer Benutzer
    Registriert seit
    26.06.2007
    Beiträge
    6

    Standard Aufruf von Update vor einem Update auf gleiche Tabelle

    Liebe Forumgemeinde,

    der Threadtitel ist etwas verwirrend aber hier zu meinem Problem.

    Ich habe eine Tabelle in der ich ein Ranking speichern möchte. Dieses Ranking fängt bei 0 an und geht mit fortlaufenden Zahlen weiter nach oben. Nach einigen Inserts könnte die Tabelle folgendermaßen aussehen:

    Code:
    Titel:                             Ranking:
    Eins                               0
    Zwei                              1
    Drei                               2
    Jetzt möchte ich in meiner Applikation (C++) allerdings auch erlauben, dass ein anderes Buch auf den Platz 1 gelangen kann. Dazu würde ich gerne einen Trigger schreiben, der dann dafür sorgt, dass alle Bücher mit einem höheren Ranking um eins erhöht werden. Nach einem Eintrag soll der Trigger also dafür sorgen, dass die Rankingreihenfolge konsistent ist:

    Code:
    Titel:                             Ranking:
    Eins                               0
    Neues Buch                     1
    Zwei                              2
    Drei                               3
    Für den Insert- und den Delete-Fall (hier müssten Einträge um 1 verringert werden) kann ich mir das schon ganz gut vorstellen aber was passiert bei einem Update?

    Nehmen wir im letzten Beispiel an, das Buch mit dem Titel "Drei" würde jetzt auf Ranking '0' gelangen. Hierzu würde meine Applikation ein Update aufrufen. Innerhalb meiner Trigger-Funktion müsste ich wieder ein Update aufrufen, was dann implizit wieder den Update-Trigger auslöst usw. bis ein Stack-Overflow eintritt.

    Gibt es generell - ohne mein Beispiel komplett zu berücksichtigen - eine Lösung für so ein Problem.? Oder liege ich mit dem Mechanismus des Triggers hier falsch und es gibt noch eine bessere Möglichkeit das über die DB abzubilden?

    Viele Dank für Eure Hilfe,
    --Heiko

  2. #2
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von Heisp Beitrag anzeigen
    Liebe Forumgemeinde,


    Gibt es generell - ohne mein Beispiel komplett zu berücksichtigen - eine Lösung für so ein Problem.? Oder liege ich mit dem Mechanismus des Triggers hier falsch und es gibt noch eine bessere Möglichkeit das über die DB abzubilden?

    Viele Dank für Eure Hilfe,
    --Heiko

    Das Problem ist, daß das nicht performen wird. Ein anderer Ansatz wäre hier, die Ranking-Spalte vielleicht als float nehmen, dann kannst Du faktisch immer einen Datensatz irgendwo einfügen, ohne daß Du alle anderen Datensätze danach updaten mußt. Ditto beim Delete bzw. beim ändern des Rankings.

    Ansonsten, schau mal in Google nach 'linked list'.

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

  3. #3
    Heisp ist offline Neuer Benutzer
    Registriert seit
    26.06.2007
    Beiträge
    6

    Standard

    Zitat Zitat von akretschmer Beitrag anzeigen
    Das Problem ist, daß das nicht performen wird.
    Andreas
    Hallo,

    leider verstehe ich nicht was das genau heißen soll aber trotzdem danke dür die Idee mit den floating-points. Mal ganz davon abgesehen ist es mir eben doch gelungen das Problem zu lösen.

    Ich habe jetzt einen zeilenbasierten Trigger (FOR EACH ROW), der nach einem UPDATE ausgeführt wird. Nehmen wir an wir haben wieder folgenden Zustand:
    Code:
    ID:              Titel:               Ranking:
    1                 Ein Buch          0
    2                 Zwei Bücher     1
    3                 Drei Bücher      2
    Das Buch mit dem Titel "Drei Bücher" soll jetzt das Ranking '0' erhalten. Also führe ich ein Update auf der Tabelle 'Buch' aus:

    Code:
    UPDATE t_buch
    SET ranking=0
    where ID=3;
    Das führt direkt vor der Ausführung meines Triggers zu folgender Tabelle:

    Code:
    ID:              Titel:               Ranking:
    1                 Ein Buch          0
    2                 Zwei Bücher     1
    3                 Drei Bücher      0                    <--
    Der AFTER Trigger muss jetzt alle Zeilen finden, die ebenfalls das Ranking '0' haben, aber nicht die ID=3 haben. Für einen solchen Datensatz ist das Ranking um '1' zu erhöhen.

    Es kommt also zu folgender Tabelle:

    Code:
    ID:              Titel:               Ranking:
    1                 Ein Buch          1                  <--
    2                 Zwei Bücher     1
    3                 Drei Bücher      0
    Durch das Update-Kommando des Triggers wird ja genau dieser Trigger - jetzt nur mit anderen Parametern - erneut ausgelöst. Im nächsten Schritt werden alle Zeilen gesucht, die ebenfalls das Ranking 1 haben jedoch nicht die ID '1'.

    Es kommt also zu folgender Tabelle:

    Code:
    ID:              Titel:               Ranking:
    1                 Ein Buch          1                  
    2                 Zwei Bücher     2               <--
    3                 Drei Bücher      0
    Durch das Update wird der Trigger wieder ausgelöst. Er sucht nach Zeilen, die ein Ranking von 2 aber eine ID != '2' haben. Da es eine solche Zeile nicht gibt, ist der Vorgang hiermit beendet und der Trigger wird - zumindest durch diesen Statement - nicht erneut gefeuert.

    Wen es interessiert hier noch der getestete Quellcode für den UPDATE-Zweig:
    Code:
    DECLARE
    	counter INTEGER;
    BEGIN
      IF (TG_OP = 'DELETE') THEN
    	
    	...
    
    	return OLD;
    
      ELSIF (tg_op = 'INSERT') THEN
    	
    	...
    
    	RETURN NEW;
      ELSIF (tg_op = 'UPDATE') THEN
    	
    	SELECT count(id) into counter from t_buch
    	WHERE ranking = NEW.ranking
    	AND id <> NEW.id;
    
    	
    	IF ( counter = 1 ) THEN
    		UPDATE t_buch
    		SET ranking = ranking+1
    		WHERE ranking = NEW.ranking 
    		AND id <> NEW.id;
    	ELSIF ( counter > 1 ) THEN
    		RAISE EXCEPTION 'COUNTER cannot be greater than 1.';
    	END IF;
    	
    	RETURN NEW;
      END IF;
    END
    Vielen Dank für Eure Hilfe,
    --Heiko

  4. #4
    akretschmer ist offline Super-Moderator
    Registriert seit
    29.10.2006
    Ort
    Dresden
    Beiträge
    5.472

    Standard

    Zitat Zitat von Heisp Beitrag anzeigen
    Hallo,

    leider verstehe ich nicht was das genau heißen soll aber trotzdem danke dür die Idee mit den floating-points. Mal ganz davon abgesehen ist es mir eben doch gelungen das Problem zu lösen.


    Vielen Dank für Eure Hilfe,
    --Heiko

    Nun, möglicherweise wirst Du bei großen Tabellen Laufzeitprobleme (schlechte Performance) haben. Es sind recht viele Updates nötig, es entstehen viele geänderte Zeilen (dead tuples).

    Andreas
    --
    ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
    https://www.xing.com/profile/Andreas_Kretschmer7

Ähnliche Themen

  1. Problem Umsortierung von Datensätzen mit nur einem SQL-Aufruf
    Von MatthiasR im Forum SQL
    Antworten: 7
    Letzter Beitrag: 29.07.2011, 09:19
  2. Problem Wie finde ich heraus welche Spalten von einem Update betroffen sind?
    Von Petro im Forum Trigger und Funktionen
    Antworten: 9
    Letzter Beitrag: 16.06.2009, 15:56
  3. Update von nur einem Teil eines Wertes in einer Spalte?
    Von buliwyf im Forum Andere Datenbanken
    Antworten: 4
    Letzter Beitrag: 02.02.2009, 11:23
  4. Automatisches Update einer Id in Tabelle
    Von Kai im Forum Allgemeines
    Antworten: 6
    Letzter Beitrag: 19.09.2008, 17:20
  5. Antworten: 11
    Letzter Beitrag: 01.06.2008, 21:01

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Links: Tobias Bauer - IT- und Funkdienstleistungen   -   Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen   -   Funkforum