【问题标题】:Updating multiple columns in Postgresql在 Postgresql 中更新多个列
【发布时间】:2021-12-28 05:15:08
【问题描述】:

我有一个名为 Availability(uname, date, start_time, end_time) 的表,用户可以在其中输入他们空闲的时间段。现在我想在插入或更新可用性表之前创建一个触发器,以检查新输入是否与同一用户在同一日期的现有可用性重叠。如果重叠,我想合并两个时隙。到目前为止,这是我的代码:

create or replace function check_overlap()
returns trigger as $$
begin
    update availability a0
    set (a0.start_time, a0.end_time) =
        case (select a.start_time, a.end_time from availability a where a.uname = new.uname and a.start_date = new.start_date)
            when NEW.start_time < a0.start_time and NEW.end_time < a0.end_time then row(NEW.start_time, a0.end_time)
            when NEW.start_time > a0.start_time and NEW.end_time > a0.end_time then row(a0.start_time, NEW.end_time)
            when NEW.start_time < a0.start_time and NEW.end_time > a0.end_time then row(NEW.start_time, NEW.end_time)
            when NEW.start_time > a0.start_time and NEW.end_time < a0.end_time then row(a0.start_time, a0.end_time)
        end;
end;
$$ language plpgsql;

create trigger tg_INSERT_UPDATE_avail
before insert or update
on availability
for each row
execute function check_overlap();

现在,问题是我遇到了这个错误:

ERROR:  source for a multiple-column UPDATE item must be a sub-SELECT or ROW() expression
LINE 3:   case (select a.s_time, a.e_time from availability a where ...
          ^

感谢任何见解!

【问题讨论】:

  • 您实际上并没有检查任何重叠。在触发函数中你必须返回一些东西(例如return new)。您也不会阻止触发 UPDATE 或 INSERT 发生,因此您不会真正“合并”两个条目。如果您使用ranges 提供高效的operators 来检查重叠或合并两个范围,这可能会容易得多。但是你仍然需要阻止原始语句发生。

标签: sql postgresql plpgsql


【解决方案1】:

您可以简单地将SELECT 移到CASE 语句之外:

update availability a0 set (a0.start_time, a0.end_time) = (
    select case when NEW.start_time < a0.start_time and NEW.end_time < a0.end_time then row(NEW.start_time, a0.end_time)
        when NEW.start_time > a0.start_time and NEW.end_time > a0.end_time then row(a0.start_time, NEW.end_time)
        when NEW.start_time < a0.start_time and NEW.end_time > a0.end_time then row(NEW.start_time, NEW.end_time)
        when NEW.start_time > a0.start_time and NEW.end_time < a0.end_time then row(a0.start_time, a0.end_time)
        else row(NEW.start_time, NEW.end_time)
    end
    from availability a where a.uname = new.uname and a.start_date = new.start_date
);

顺便说一句:我无法对此进行测试,但没有 where 子句的更新对我来说看起来很奇怪。

【讨论】:

    猜你喜欢
    • 2021-02-04
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多