0

插入代码

INSERT INTO employee (pid, pname, desig, dept, lts_i, lts_O, p_status) VALUES %s \
                    ON CONFLICT (pid) DO UPDATE SET \
                    (pname, desig, dept, lts_i, lts_O, p_status) = \
                    (EXCLUDED.pname, EXCLUDED.desig, EXCLUDED.dept, EXCLUDED.lts_i, EXCLUDED.lts_O, EXCLUDED.p_status) \
                    RETURNING *

如果我像上面那样插入,那么它工作得很好。而不是 CONFLICT 我使用了以下功能

CREATE FUNCTION employee_db(
  pid1 integer,
  pname1 text,
  desig1 text,
  dept1 text,
  lts_i1 time,
  lts_o1 time,
  p_status1 text
) RETURNS VOID AS
$$
BEGIN
LOOP
-- first try to update the key
-- note that "a" must be unique
UPDATE employee SET (lts_i, lts_o, p_status) = (lts_i1, lts_o1, p_status1) WHERE pid = pid1;
IF found THEN
RETURN;
END IF;
-- not there, so try to insert the key
-- if someone else inserts the same key concurrently,
-- we could get a unique-key failure
BEGIN
INSERT INTO employee(pid, pname, desig, dept, lts_i, lts_o, p_status) VALUES (pid1, pname1, desig1, dept1, lts_i1, lts_o1, p_status1);
RETURN;
EXCEPTION WHEN unique_violation THEN
-- do nothing, and loop to try the UPDATE again
END;
END LOOP;
END;
$$
LANGUAGE plpgsql;

这需要一些论据

SELECT merge_db(12, 'Newton', 'director', 'd1', '10:00:26', '00:00:00', 'P-Status')"

但是当我在同一 id(12) 内更新 lts_i、lts_O 和 p_status

SELECT merge_db(12, 'Newton', 'director', 'd1', '12:10:22', '02:30:02', 'active')"

然后它也显示重复键错误。我不想在这里使用 CONFLICT,因为我在同一个表上有一个 UPDATE RULE,并且 postgresql 已经说“该事件是 SELECT、INSERT、UPDATE 或 DELETE 之一。请注意,包含 ON CONFLICT 子句的 INSERT不能用于具有 INSERT 或 UPDATE 规则的表。请考虑改用可更新视图。”

更新规则

CREATE RULE log_employee AS ON UPDATE TO employee
    WHERE NEW.lts_i <> OLD.lts_i or NEW.lts_O <> OLD.lts_O
    DO UPDATE employee set today = current_date where id = new.id;

如果 lts_i、lts_o 或 p_status 已更新,则将 current_date 插入同一员工表中的“今天”字段。

但绝对我需要规则,在这种情况下我该怎么办?

任何帮助,将不胜感激。谢谢。

4

1 回答 1

1

您应该为此使用触发器。

触发功能:

create function emp_trigger_func()
  returns trigger
as
$$
begin
   new.today := current_date;
   return new;
end;
$$
language plpgsql;

最好在触发器定义中完成有关何时更新该列的条件,以避免不必要地触发触发器

create trigger update_today
  before update on employee
  for each row
  when (NEW.lts_i <> OLD.lts_i or NEW.lts_O <> OLD.lts_O)
  execute procedure emp_trigger_func();

请注意,<>它没有正确处理NULL值。如果lts_iorlts_o可以包含空值,那么触发条件最好写成:

  when (   NEW.lts_i is distinct from OLD.lts_i 
        or NEW.lts_O is distinct from OLD.lts_O)

这也将捕捉到null值的变化。

于 2019-03-27T09:59:12.773 回答