SELECT p.pid, p.name, h_rel.hid
FROM   person p, hobbies h_rel, hobby h
WHERE  p.pid = h_rel.pid AND h_rel.hid = h.name
;


-- Funktioniert wegen ON UPDATE CASCADE.
UPDATE hobby
   SET name = 'Accordion'
 WHERE name = 'Akkordeon'
;

SELECT p.pid, p.name, h_rel.hid
FROM   person p, hobbies h_rel, hobby h
WHERE  p.pid = h_rel.pid AND h_rel.hid = h.name
;


-- Funktioniert wegen ON DELETE CASCADE.
DELETE FROM hobby
WHERE  name = 'Accordion'
;

SELECT p.pid, p.name, h_rel.hid
FROM   person p, hobbies h_rel, hobby h
WHERE  p.pid = h_rel.pid AND h_rel.hid = h.name
;


/* Anstelle von ON UPDATE CASCADE könnte man auch einen Trigger verwenden. */

-- Funktioniert laut SQL-Standard, aber nicht in PostgreSQL. 
/*
CREATE TRIGGER cascading_hobby_update
AFTER UPDATE ON hobby
  REFERENCING OLD ROW AS old, NEW ROW AS new 
FOR EACH ROW
WHEN (new.name <> old.name)
  UPDATE hobbies
  SET    hid=new.name
  WHERE  hid=old.name
;
*/

-- Es gibt aber proprietäre Trigger in PostgreSQL.

/*
Die Datenbank sollte noch einmal erzeug werden, diesmal ohne:
  ON DELETE CASCADE ON UPDATE CASCADE
*/

-- Funktioniert nicht mehr, da ON UPDATE CASCADE fehlt.
/*
UPDATE hobby
   SET name = 'Accordion'
 WHERE name = 'Akkordeon'
;
*/

-- Zunächst muss die Erweiterung "plpgsql" in der Datenbank aktiviert werden
-- (einmal pro Datenbank)-- 

/*
DROP LANGUAGE IF EXISTS  'plpgsql' CASCADE;

CREATE TRUSTED LANGUAGE 'plpgsql'
  HANDLER plpgsql_call_handler
  VALIDATOR plpgsql_validator
;
*/

-- Dann muss eine Trigger-Funktion definiert werden.

CREATE OR REPLACE FUNCTION rename_hobbies()
  RETURNS TRIGGER AS
$BODY$
  BEGIN
    IF NEW.name <> OLD.name THEN
      UPDATE hobbies
      SET    hid=NEW.name
      WHERE  hid=OLD.name;
    END IF;
    RETURN NEW;
  END
$BODY$
  LANGUAGE 'plpgsql';

-- Nun kann der eigentliche Trigger definiert werden.

DROP TRIGGER IF EXISTS update_hobby ON hobby;
CREATE TRIGGER update_hobby
  AFTER UPDATE ON hobby
FOR EACH ROW
  EXECUTE PROCEDURE rename_hobbies();

-- Funktioniert wegen TRIGGER (und verzögerter Überprüfung
-- der Integritätsbedingungen: DEFERRABLE INITIALLY DEFERRED).
UPDATE hobby
   SET name = 'Accordion'
 WHERE name = 'Akkordeon'
;

SELECT p.pid, p.name, h_rel.hid
FROM   person p, hobbies h_rel, hobby h
WHERE  p.pid = h_rel.pid AND h_rel.hid = h.name
;

