【问题标题】:PostgreSQL UPDATE trigger on SELECT using IF/ELSE statements使用 IF/ELSE 语句在 SELECT 上触发 PostgreSQL UPDATE
【发布时间】:2018-09-17 16:39:52
【问题描述】:

我想做的是在t2 更新时更新t1。但是,我需要使用表 t3 来加入它们,这意味着我需要一个子查询。当满足一个条件时,我可以成功更新t1;但是,当涉及多个条件时,我无法理解用于更新的语法——本质上我在组合 postgresql UPDATEIF/ELSEIF/ELSE 和子查询时遇到了麻烦。我正在寻找类似的东西:

-- TABLES

create table t1
(
serial_number        integer primary key,
current_location     varchar
);

create table t2
(
some_id              bigserial primary key,
status               integer
);

create table t3
(
serial_number        integer REFERENCES t1(serial_number),
some_id              integer REFERENCES t2(some_id),
unique(serial_number, some_id)
);


-- TRIGGER

create or replace function trigger_update_currentlocation()
returns trigger as 
$body$
begin

-- If SUBQUERY status is deployed (0), retrieved (1), or lost (2), then update t1 with appropriate current_location. 

-- THIS IS WHAT FAILS - SQL does not recognize 'SUBQUERY.status' in each if/elseif statement.
update t1
    if SUBQUERY.status = 0 then
        set t1.current_location = 'Deployed'

    elseif SUBQUERY.status = 1 then
        set t1.current_location = 'Retrieved'

    elseif SUBQUERY.status = 2 then
        set t1.current_location = 'Lost'

-- This joins t3 and t2 in order to select only serial_numbers with a status. Column `some_id` does not exist in t1 and thus can't be used to join t1 to t3 directly. 
from (
    select t3.serial_number, t2.status
    from t2 inner join t3
        on t2.some_id = t3.some_id
    ) as SUBQUERY

-- This matches SUBQUERY serial number to t1 serial number, so that only the appropriate rows in t1 are updated.
where SUBQUERY.serial_number = t1.serial_number;

end;
$body$
language plpgsql;

CREATE TRIGGER "deployLocations" AFTER update ON t2 FOR EACH ROW EXECUTE 
PROCEDURE trigger_update_currentlocation();

【问题讨论】:

    标签: sql postgresql if-statement sql-update


    【解决方案1】:

    这个查询应该做你需要的:

    update t1 
      set current_location = 
        case t2.status
            when 0 then 'Deployed'
            when 1 then 'Retrieved'
            when 2 then 'Lost'
        end
    from t2 inner join t3
       on t2.some_id = t3.some_id
    where t3.serial_number = t1.serial_number;
    

    【讨论】:

    • 我真的很喜欢这很简单,谢谢。有没有办法调整它以包含多个列更新?我尝试在case 语句的end 之后添加set date_updated = now(),以便记录此触发器何时触发。
    • 想通了 - 多次使用 set 这个词,而不是简单的逗号。
    【解决方案2】:

    将 if else 替换为更新中的 case 语句,它将解决您遇到的问题。

    update t1
            set t1.current_location =   CASE  
                                        WHEN SUBQUERY.status = 0 THEN 'Deployed' 
                                        WHEN SUBQUERY.status = 1 THEN 'Retrieved' 
                                        WHEN SUBQUERY.status = 2 THEN 'Lost' 
                                        ELSE t1.current_location
                                    END 
    from (
        select t3.serial_number, t2.status
        from t2 inner join t3
            on t2.some_id = t3.some_id
        ) as SUBQUERY
    
    where SUBQUERY.serial_number = t1.serial_number;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-15
      • 2012-11-11
      • 1970-01-01
      • 2021-10-23
      • 2014-11-03
      • 1970-01-01
      • 2019-06-12
      • 2019-04-09
      相关资源
      最近更新 更多