Databasteknik: Lösningar till teoriövning 9

Uppgift 1

...

Uppgift 2

...

Följdfrågor: Förklara vad en cursor är, och hur den används. Vad menas med impedance mismatch?

Uppgift 3

Med Mimer-syntax:
@
create trigger kolla_förlust after insert on Deltagare
    referencing new table as n
for each row
begin atomic
    declare robot integer;
    declare resultat varchar(8);
    select n.robot into robot from n;
    select n.resultat into resultat from n;
    if resultat = 'Förlust' then
        update Robotar set Vikt = Vikt * 0.9 where Nummer = robot;
    end if;
end
@
Men notera att Mimer inte har for each row, bara for each statement. Om man använder for each statement i triggern ovan fungerar det ändå så länge man bara lägger in en rad åt gången.

Följdfråga: Vad menas med en ECA-regel?

Uppgift 4

a) Nej.

Följdfråga: Varför?

b) Ja.

Följdfråga: Varför?

c) Först skapar vi en tabell för att lagra den materialiserade vyn:

CREATE TABLE Robotviktsumma
(Totalvikt INTEGER,
-- A trick to allow only one row in this table:
OneRowNumber INTEGER UNIQUE DEFAULT 1,
CHECK (OneRowNumber = 1));
Lägg in aktuell viktsumma:
INSERT INTO Robotviktsumma (Totalvikt) SELECT SUM(Vikt) FROM Robotar;
Tre triggers (med Mimer-syntax):
@
create trigger robot_insert after insert on Robotar
    referencing new table as n
for each row
begin atomic
    declare nyvikt integer;
    select Vikt into nyvikt from n;
    update Robotviktsumma set Totalvikt = Totalvikt + nyvikt;
end
@

@
create trigger robot_delete after delete on Robotar
    referencing old table as o
for each row
begin atomic
    declare bortvikt integer;
    select Vikt into bortvikt from o;
    update Robotviktsumma set Totalvikt = Totalvikt - bortvikt;
end
@

@
create trigger robot_update after update on Robotar
    referencing old table as o new table as n
for each row
begin atomic
    declare bortvikt integer;
    declare nyvikt integer;
    select Vikt into bortvikt from o;
    select Vikt into nyvikt from n;
    update Robotviktsumma set Totalvikt = Totalvikt - bortvikt + nyvikt;
end
@
Men notera att Mimer inte har for each row, bara for each statement. Om man använder for each statement i triggern ovan fungerar det ändå så länge man bara lägger in, tar bort eller ändrar en rad åt gången.

Om man byter ut Vikt mot sum(Vikt) fungerar det även med for each statement och flera tabellrader som påverkas av samma kommando.

Uppgift 5

@
create trigger kolla_vinst after insert on Deltagare
    referencing new table as n
for each row
begin atomic
    declare resultat varchar(8);
    declare striden integer;
    declare denna_robot integer;
    declare denna_vikt integer;
    select n.resultat into resultat from n;
    if resultat = 'Vinst' then
        select n.strid into striden from n;
        select n.robot into denna_robot from n;
        select vikt into denna_vikt from Robotar where Nummer = denna_robot;
        if exists (select * from Deltagare, Robotar as motståndare
                   where Deltagare.robot = motståndare.Nummer
                   and Deltagare.strid = striden
                   and motståndare.Vikt > denna_vikt) then
            -- Bara för att få ett fel som avbryter transaktionen:
            set denna_robot = denna_robot / 0;
       end if;
    end if;
end
@

Uppgift 6

Det blir en loop, där en ändring i tabellen Robotar gör att (exempelvis) triggern robot_update aktiveras, och ändrar i tabellen Robotviktsumma. Då aktiveras triggern dumregel, som ändrar i tabellen Robotar, som aktiverar robot_update, och så vidare i en oändlig loop.

Mimer ger ett felmeddelande, och transaktionen avbryts med rollback:

Mimer SQL error -11047 in function EXECUTE
         The maximum number of recursive invocations has been exceeded
Mimer SQL error -14703 in function EXECUTE
         An exception occurred during the execution of the trigger SYSADM.robot_update
Följdfråga: Är det lättare eller svårare att felsöka en applikation som använder regler som påverkar varandra, jämfört med ett vanligt program?


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 4 december 2022