使用PSQL中的函数仅更新最后更新的行

时间:2018-08-31 11:17:01

标签: postgresql function timestamp database-trigger

我正在使用一个功能,该功能将从到达和离开的时间计算工作时间。

我的功能如下:

CREATE FUNCTION Sati_rada() 
  RETURNS TRIGGER 
as $Update$ 
BEGIN
    update radni_sati 
        set sati_rada=(select (current_date + (odlazak-dolazak)) 
                       from radni_sati 
                       where datum=current_date 
                       and dolazak IS NOT NULL 
                       LIMIT 1)
  WHERE datum=current_date 
    AND odlazak IS NOT NULL 
    AND DOLAZAK IS NOT NULL; 
  RETURN NULL; 
END $Update$ 
language plpgsql;

我的触发器如下:

CREATE TRIGGER Sati_rada_trigger
AFTER UPDATE OF odlazak ON radni_sati 
FOR EACH ROW EXECUTE PROCEDURE Sati_rada();

当我要在手动更新的最后一行上使用功能时,问题就从这里开始。

例如(我从母语翻译了列的名称):

SELECT id_radni_sati as id,ime as name,dolazak as arrival, 
odlazak as departure, sati_rada as "hours of work" FROM radni_sati
WHERE datum='31/08/2018';

  id   |  name   |       arrival       |      departure      |    hours of work
-------+---------+---------------------+---------------------+---------------------
 22282 | Nevenko | 2018-08-31 07:00:00 |                     |
 22284 | Marko   | 2018-08-31 11:41:52 | 2018-08-31 12:01:45 | 2018-08-31 00:19:53

如果我手动尝试更改一行的出发时间:

UPDATE radni_sati SET odlazak='31/08/2018 07:05:00' where id_radni_sati=22282;

发生这种情况:

postgres=# select id_radni_sati as id,ime as name,dolazak as arrival,
odlazak as departure, sati_rada as "hours of work" from radni_sati 
where datum='31/08/2018';
  id   |  name   |       arrival       |      departure      |    hours of work
-------+---------+---------------------+---------------------+---------------------
 22282 | Nevenko | 2018-08-31 07:00:00 | 2018-08-31 07:05:00 | 2018-08-31 00:05:00
 22284 | Marko   | 2018-08-31 11:41:52 | 2018-08-31 12:01:45 | 2018-08-31 00:05:00
(2 rows)

我的问题是:每当列odlazak更新时,如何计算数据库中单行的工作时间(需要更新的时间)?

1 个答案:

答案 0 :(得分:1)

问题出在触发函数中的更新语句。它应该使用更新后的行的ID来确保它仅更新正确的记录。

这是设置:

CREATE TABLE t (id INTEGER, arrival TIMESTAMP, departure TIMESTAMP, hours_of_work TIME);

CREATE OR REPLACE FUNCTION public.trig()
        RETURNS TRIGGER AS $$
BEGIN
        UPDATE t
        SET hours_of_work = NEW.departure - NEW.arrival
        WHERE id = NEW.id;

        RETURN NULL;
END
        $$ LANGUAGE plpgsql;


CREATE TRIGGER t_trig
AFTER UPDATE OF departure ON public.t 
FOR EACH ROW EXECUTE PROCEDURE public.trig();

INSERT INTO t VALUES (1, NOW(), NOW() + INTERVAL '1 hour', (NOW() + INTERVAL '1 hour') - NOW());
INSERT INTO t VALUES (2, NOW(), NOW() + INTERVAL '1 hour');

表如下:

enter image description here

现在更新:

UPDATE t SET departure = NOW() + INTERVAL '2 hours' WHERE id = 2;

表格现在是:

enter image description here


因此,您应该更改

update radni_sati 
    set sati_rada=(select (current_date + (odlazak-dolazak)) 
                   from radni_sati 
                   where datum=current_date 
                   and dolazak IS NOT NULL 
                   LIMIT 1)   WHERE datum=current_date 
AND odlazak IS NOT NULL 
AND DOLAZAK IS NOT NULL;

UPDATE radni_sati
SET sati_rada = current_date + (NEW.odlazak - NEW.dolazak)
WHERE id_radni_sati = NEW.id_radni_sati;