1

Temat: Problem z kursorek

Witam,

mam dość kłopotliwy i zapewne łatwy do rozwiązania błąd, który od kilku dni spędza mi sen z powiek. Mam taki oto kod:

CREATE FUNCTION czas_pracy (integer,date,date)
RETURNS time
AS $$
    DECLARE
        id ALIAS FOR $1;
        od ALIAS FOR $2;
        do ALIAS FOR $3;
        razem time:='00:00';
        id_motor integer;
        data_k date;
        cz_wyj time;
        cz_przyj time;
   
    BEGIN
    --BEGIN TRANSACTION;
    DECLARE cz_pr CURSOR
        FOR SELECT id_motorniczy, data_kurs, czas_wyjazd, czas_przyjazd FROM kurs;

    --OPEN cz_pr;
    FETCH 1 FROM cz_pr INTO id_motor, data_k, cz_wyj, cz_przyj;

    WHILE FOUND LOOP
        IF id_motor=id AND data_k BETWEEN od AND do AND cz_przyj IS NOT NULL
        THEN
            razem:=razem + (cz_przyj - cz_wyj);
        END IF;

        FETCH 1 FROM cz_pr INTO id_motor, data_k, cz_wyj, cz_przyj;
    END LOOP;

    CLOSE cz_pr;
    --COMMIT TRANSACTION;

    RETURN razem;
    END;
$$ LANGUAGE 'PLPGSQL';

i nie mam zielonego pojęcia czemu nie działa, więc mam taką małą prośbę - moglibyście na to zerknąć i pomóc mi rozwiązać ten problem?
Z góry dzięki za poświęcenie czasu wink

2

Odp: Problem z kursorek

Używanie kursorów w funkcjach jest bardzo typowym przykładem czegoś co "przynoszą" ze sobą ludzie z innych baz, a co w postgresie jest całkowicie niepotrzebne, wręcz czasem szkodliwe.

W szczególności, twoją funkcję można uprościć do postaci pojedynczego zapytania:

select sum(czas_przyjazd - czas_wyjazd) from kurs where data_kurs between $2 and $3 and id_motorniczy = $1;

I to wszystko. Robienie ręcznej iteracji po rekordach, zwłaszcza - wszystkich rekordach, by ręcznie nałożyć warunki z IF'a jest całkowicie nieuzasadnialne - jedyne co uzyskasz to znaczne spowolnienie.

Do iterowania po recordsetach użyj normalnej pętli:

declare
    temprec record;
begin
    for temprec in select * from kurs loop
        if temprec.id_motorniczy = ....
        ...
    end loop;
    ...
end;

--
The best thing about modern society is how easy it is to avoid contact with it.

3

Odp: Problem z kursorek

Dzięki za pomoc wink Masz rację - to moja "zaleciałość" z MSSQL - po prostu dostałam kawałek kodu w MSSQL i miałam go przerobić na PostgreSQL, więc się trochę pogubiłam... I jeszcze raz wielkie dzięki wink