【问题标题】:Postgresql Trigger updating entire column instead of specific rowsPostgresql 触发器更新整个列而不是特定行
【发布时间】:2021-09-08 03:22:54
【问题描述】:

我想要实现的是,当我执行 UPDATE 语句时,我希望 TRIGGER 更新具有 insurance_team = 'professional'expiration_date = current_date 的每一行>,只需将到期年份+1。

我当前的 TRIGGER 函数虽然更新了整个列。

表格

CREATE TABLE insurance_premiums (
    contract_code text NOT NULL,
    insurance_team text NOT NULL,
    starting_date date NOT NULL,
    expiration_date date NOT NULL,
    contract_cost float8 NOT NULL,
    vehicle_contract text NOT NULL,
    customer_contract text NOT NULL,
    driver_contract text NOT NULL,
    CONSTRAINT insurance_premiums_pkey PRIMARY KEY (contract_code)
);

触发器

create trigger update_contract after
update
    on
    public.insurance_premiums for each row execute function new_date()

触发函数

CREATE OR REPLACE FUNCTION public.new_date()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
    BEGIN 
        if old.insurance_team = 'professional' then
            if old.expiration_date = CURRENT_DATE then
                new.expiration_date = old.expiration_date + integer '365';
                update insurance_premiums set expiration_date = new.expiration_date;
            end if;
        end if;
        return new;
    END;
$function$
;

更新示例

UPDATE insurance_premiums 
SET contract_cost = 736.33
WHERE contract_code = 'EI-36653';

插入上面的例子:

INSERT INTO insurance_premiums (contract_code, insurance_team, starting_date, expiration_date, contract_cost, vehicle_contract, customer_contract, driver_contract) 
VALUES('EI-36653', 'professional', '2019-03-31', '2021-06-24', 12736.3, 'Sprinter', 'Antoine Burgise', 'Prudence Lacer');

旁注:上面的更新语句只是一个测试触发器的例子。

【问题讨论】:

  • 丢失update insurance_premiums ... 部分。您已经为该行设置了new.expiration_date。您的 UPDATE 没有 WHERE 将其限制为特定行,无论如何都是多余的。
  • @AdrianKlaver 如果我从函数中删除更新查询,那么它不会更新任何内容。对于 where 部分,我认为 if 语句已经涵盖了我。
  • 使用BEFORE UPDATE 触发器。

标签: sql postgresql


【解决方案1】:

根本不使用 UPDATE。

定义触发器为before update触发器:

create trigger update_contract 
  BEFORE updateupdate
  on public.insurance_premiums 
  for each row execute function new_date()

那么赋值new.expiration_date := ..就够了:

CREATE OR REPLACE FUNCTION public.new_date()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN 
  if old.insurance_team = 'professional' AND old.expiration_date = CURRENT_DATE then
    new.expiration_date := old.expiration_date + integer '365'; --<<< this is enough
  end if;
  return new;
END;
$function$
;

【讨论】:

  • 那是我的错,我没有使用 := 运算符,而是使用了 = 运算符,这就是它不起作用的原因,所以我使用了 update 语句。但这仅在我对该特定类别的合同执行更新查询时才有效。例如,如果我从“半”类别更新合同,那么它不会更新属于“专业”类别的每个合同。由于我使用for each row,我认为它也会影响其他人。我错了吗?
  • 为了设置变量:== 相同,请参见assignment。你真的需要花一些时间阅读这个plpgsql,尤其是这个trigger functions和这个CREATE TRIGGER
  • @bokos21:触发器将在每行发生更改时触发一次。因此,触发器 function 将为您的 UPDATE 更改的每一行调用。 :== 在 PL/pgSQL 中是相同的 - 我只使用 := 因为我一直使用它(并且有一段时间不鼓励使用 = 进行赋值)
猜你喜欢
  • 2017-09-20
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多