Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

UDF und Trigger

Dieses Thema im Forum "PostgreSQL" wurde erstellt von blabberblau, 13 Juni 2020.

  1. blabberblau

    blabberblau Neuer Benutzer

    Guten Abend,

    ich steh vor folgender Aufgabe.
    Geben Sie UDFs und Trigger an, die sicher stellen, dass jede Vorlesung nur von demjenigen Professor gepruft wird, der sie auch liest.

    Meine Ralationen lauten

    1: Vorlesungen : Vorlnr(Primary Key), titel, sws, gelesen_von
    2: pruefen: matrnr, vorlnr, persnr, note, sws


    Mein Problem ist nun, ich möchte die UDF & Trigger erstelle, damit vor dem einfügen geprüft wird, dass der Prüfende(persnr von pruefen) auch dem Vorleser(gelesen_von ) entspricht. Verzweifele schon ewig daran. Kann mir jemand behilflich sein?

    Beste Grüße, Marco
     
  2. akretschmer

    akretschmer Datenbank-Guru

    warum so umständlich? Wenn Die in Vorlesungen den PK auf vorlnr+gelesen_von setzt, dann kannst Di den FK in pruefen auf vorlnr+persnr setzen und hast exakt das, was Du willst. Du kannst auch in pruefen die persnr weglassen, weil ja festgelegt ist, Vorleser = Prüfer sein muß.
     
  3. akretschmer

    akretschmer Datenbank-Guru

    aber damit Du auch mal eine Trigger-Demo siehst:

    Code:
    test=# create table vorlesungen(vnr int primary key, titel text, gelesen_von int);
    CREATE TABLE
    test=*# create table pruefen(vnr int references vorlesungen, persnr int);
    CREATE TABLE
    test=*# create or replace function check_pruefer() returns trigger as $$ begin if exists (select 1 from vorlesungen v where (new.vnr,new.persnr) = (v.vnr,v.gelesen_von)) then return NEW; else raise exception 'prüfer != vorleser'; end if; end;$$language plpgsql;
    CREATE FUNCTION
    test=*# create trigger check_pruefer before insert or update on pruefen for each row execute procedure check_pruefer();
    CREATE TRIGGER
    test=# insert into vorlesungen values (1, 'mathe', 1);
    INSERT 0 1
    test=*# insert into vorlesungen values (2, 'physik', 2);
    INSERT 0 1
    test=*# insert into pruefen values (1,1);
    INSERT 0 1
    test=*# insert into pruefen values (2,1);
    FEHLER:  prüfer != vorleser
    CONTEXT:  PL/pgSQL-Funktion check_pruefer() Zeile 1 bei RAISE
    test=*#
    
     
  4. blabberblau

    blabberblau Neuer Benutzer

    Guten Morgen,

    Danke für die Lösung. Definitiv ist es umständlich, aber das war eine Aufgabe einer Altklausur(ohne Lösung) und ich will das bisschen üben.
    Nochmal Danke.
    Beste Grüße
     
  5. akretschmer

    akretschmer Datenbank-Guru

    Dachte ich mir schon. Wenn Du die 2 Hinweise aus meinem ersten Posting nennt, kommst vermutlich gaaaanz groß bei raus ;-)
     
  6. blabberblau

    blabberblau Neuer Benutzer

    Hi @akretschmer,
    ich hab mich mal an eine weitere Teilaufgabe gewagt.

    Schreiben Sie UDFs und Trigger, die einen neuen Termin vergeben, wenn eine Prüfung ohne Termin ¨ eingefugt wird. Dieser Termin darf auch nicht mit anderen Prüfungen des selben Prüfers oder Studenten überlappen. Die Dauer des Termins ist 4 Minuten pro ECTS-Punkt der Prüfung, mindestens jedoch 20 und höchstens 60 Minuten.

    Die Tabelle pruefen(matrnr, vorlnr, persnr, note, sws, startzeitpunkt, endzeitpunkt)

    Mein Code lautet

    Code:
    create or replace function termin() returns TRIGGER as $$
    declare
        startT timestamp;
        endT timestamp;
        laenge int;
        sws int := new.sws;
    begin
        if new.startzeitpunkt = NULL or new.endzeitpunkt = NULL then
            laenge := 4*sws;
            if laenge < 20 then laenge := 20;
            elseif laenge > 60 then laenge := 60;
            end if;
                startT := (select max(p.endzeitpunkt) from pruefen p where p.matrnr = new.matrnr or p.persnr = new.persnr);
                startT := startT + (69 * interval '1 second');
                endT := startT + (laenge * interval '1 minute');
                update pruefen p set startzeitpunkt = startT, endzeitpunkt = endT
                where p.matrnr = new.matrnr and p.vorlnr = new.vorlnr and p.persnr = new.persnr and p.note = new.note and p.startzeitpunkt = NULL and p.endzeitpunkt = NULL;
        end if;
        return new;
       
    end
    $$ Language plpgsql;
    
    create trigger newTermin
    after insert on pruefen
    for each row
    execute procedure termin();
    
    Beim testen fügt er keine Start und Endzeitpunkt ein :-( Woran könnte das liegen?
    Und ein weiteres Problem ist, wenn eine gleiche Prüfung eingetragen wird und da kein Prüfungszeitpunkt eingetragen ist, ändert er das auch ab. Wenn ich das Problem mit instead of löse, springt er doch in eine Endlosschleife. Wie kann ich das verhindern?

    Beste Grüße
     
  7. akretschmer

    akretschmer Datenbank-Guru

    kurz quergelesen:

    • Vergleich = NULL liefert immer NULL, geht also nicht. schaue Dir isnull an
    • in einem AFTER-Trigger ist es zu spät, an NEW zu manipulieren
    • denke auch dran, daß die Constraints nach einem UPDATE eingehalten sein sollten, nicht nur bei INSERT
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden