美文网首页
COMP9311 Database Systems Lab6

COMP9311 Database Systems Lab6

作者: Sisyphus235 | 来源:发表于2017-10-02 08:00 被阅读0次

    练习使用plpgsql建立trigger规则。
    使用的材料与lab5一致:


    ER Design

    schema文件如下:

    -- Beer rating database
    
    create table Location (
        id          serial primary key,
        state       varchar(50),  -- not every country has states
        country     varchar(50) not null
    );
    
    create table Taster (
        id          serial primary key,
        family      varchar(30),  -- some people have only one name
        given       varchar(30) not null,  
        livesIn     integer not null references Location(id)
    );
    
    create table Brewer (
        id          serial primary key,
        name        varchar(50) not null,
        locatedIn   integer not null references Location(id)
    );
    
    create table BeerStyle (
        id          serial primary key,
        name        varchar(30) not null
    );
    
    create table Beer (
        id          serial primary key,
        name        varchar(50) not null,
        style       integer not null references BeerStyle(id),
        brewer      integer not null references Brewer(id),
        totRating   integer default 0,
        nRatings    integer default 0,
        rating      float
    );
    
    create table Ratings (
        taster      integer not null references Taster(id),
        beer        integer not null references Beer(id),
        score       integer not null
                    constraint validRating
                check (score >= 1 and score <= 5)
    );
    

    What is required is a series of semi-formal assertions:

    for every Beer b (b.totRating = (sum(score) from Ratings where beer = b.id))
    for every Beer b (b.nRatings = (count(score) from Ratings where beer = b.id))
    for every Beer b (b.rating = b.totRating/b.nRatings, if b.nRatings > 0, null otherwise)
    

    Write triggers and their associated PLpgSQL functions to maintain these assertions on the Beer table in response to all possible changes to the Ratings table.

    Q1

    insertion trigger

    CREATE OR REPLACE FUNCTION insertRating()
    returns trigger
    AS $$
    DECLARE
        b Beer;
    BEGIN
        SELECT * into b FROM Beer WHERE id = New.beer;
        b.nRatings := b.nRatings + 1;
        b.totRating := b.totRating + new.score;
        b.rating = b.totRating / b.nRatings;
        UPDATE Beer
        SET nRatings = b.nRatings,
                totRating = b.totRating,
                rating = b.rating
        WHERE id = New.beer;
        return new;
    END;
    $$ LANGUAGE plpgsql;
    --新增的beer数据会使得评价数加1,总评分提高,该啤酒的评分重新计算
    
    CREATE TRIGGER InsertRating after inser on Ratings
    for each row execute procedure insertRating();
    

    Q2

    update trigger

    CREATE OR REPLACE FUNCTION updateRating()
    returns trigger
    AS $$
    DECLARE
        nb Beer;
        ob Beer;
    BEGIN
        SELECT * INTO nb FROM Beer WHERE id = New.beer;
        --因为要更新,所以一定有new,存放在nb中
        if (new.beer = old.beer) then
        --如果更新的beer和过去的beer名字一致,则减去过去的评分加上现在的评分,重新计算rating即可
            if(new.rating = old.rating) then
                null;
            else
                nb.totRating := nb.totRating + new.score - old.score;
                nb.rating := nb.totRating / nb.ratings;
        else
        --如果更新的beer和过去的beer名字不一致,那么过去的beer和新的beer数据都需要调整
            SELECT * INTO ob FROM Beer WHERE id = old.beer;
            ob.totRating := ob.totRating - old.score;
            ob.nRatings := ob.nRatings - 1;
            ob.rating := ob.totRating / ob.nRatings;
            nb.totRating := nb.totRating + new.score;
            nb.nRatings := nb.nRatings + 1;
            nb.rating := nb.totRating / nb.nRatings;
            UPDATE Beer
            SET nRatings = ob.nRatings,
                    totRating = ob.totRating,
                    rating = ob.rating
            WHERE id = old.beer;
        END if;
        UPDATE Beer
        SET nRatings = nb.nRatings,
                totRating = nb.totRating,
                rating = nb.rating
        WHERE id = new.beer;
        return new;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE TRIGGER UpdateRating after update on Ratings 
    for each row execute procedure updateRating();
    

    Q3

    delete trigger

    CREATE OR REPLACE FUNCTION deleteRating()
    returns trigger
    AS $$
    DECLARE 
        b Beer;
    BEGIN
        SELECT * INTO b FROM Beer WHERE id = old.beer;
        b.nRatings := b.nRatings - 1;
        b.totRating := b.totRating - old.score;
        if (b.nRatings = 0) then
            b.rating := null;
        else
            b.rating := b.totRating / b.nRatings;
        end if;
        UPDATE Beer
        SET nRatings = b.nRatings,
                totRating = b.totRating,
                rating = b.rating
        WHERE id = old.beer;
        return old;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE TRIGGER DeleteRating before delete on Ratings
    for each row execute procedure deleteRating();
    

    相关文章

      网友评论

          本文标题:COMP9311 Database Systems Lab6

          本文链接:https://www.haomeiwen.com/subject/rmezextx.html