postgresql Postgres触发器,用于对ID匹配的另一个表中的列求和

u0njafvf  于 2022-12-03  发布在  PostgreSQL
关注(0)|答案(1)|浏览(147)

我已经被困在这几个小时,我见过例子,但就是不能让这个工作。
我想对“BuiltResourceLines”表中的“总计”列求和,并将其放入“BuiltResources”表的总计中,其中“BuiltResourceLines”.“BuiltResourceId”=“BuiltResources”.“Id”
对于我的生活不能得到这个工作:

UPDATE dbo."BuiltResources" BR
    SET "Total" = SUM(BRL."Total")
    FROM dbo."BuiltResourceLines" BRL
    WHERE BR."Id" = BRL."BuiltResourceId";

此函数返回“无法使用聚合...”

UPDATE dbo."BuiltResources" BR
    SET "Total" = 
        (
            SELECT SUM(BRL."Total")
            FROM dbo."BuiltResourceLines" BRL 
            WHERE BRL."BuiltResourceId" = BR."Id"
        ) 
    WHERE BR."Id" = "HOW TO GET REFERENCE TO BRL HERE????;

这一个我不能得到参考BRL和我得到一个警告:不安全的查询:'Update'陈述式不含'where',一次更新所有数据表数据列
我试过大约50个其他的场景,但这些似乎最接近。
请帮帮忙。
以下是完整的触发器:

CREATE OR REPLACE FUNCTION update_builtresource_total()
    RETURNS TRIGGER
    LANGUAGE PLPGSQL
AS
$$
BEGIN

    IF TG_OP = 'UPDATE' THEN
        
        --QUERY
      
    END IF;
    RETURN NULL;

END
$$;

DROP TRIGGER IF EXISTS update_builtresource_total_trigger on dbo."BuiltResourceLines";

CREATE TRIGGER update_builtresource_total_trigger
    AFTER UPDATE
    ON dbo."BuiltResourceLines"
    FOR EACH ROW
EXECUTE PROCEDURE update_builtresource_total();
sqxo8psd

sqxo8psd1#

第二个查询不需要额外的WHERE,它已经返回了与内部表达式中当前行BR."Id"相对应的和。
一个coalesce可能会很有用,它可以防止在给定“Id”没有行时弹出空值。另外,第一个查询在两个表中的"Id"上连接,第二个查询将"Id""BuiltResourceId"连接,这样更有意义。Updated demo:

create schema dbo;
create table dbo."BuiltResources" (
  "Id" serial primary key, 
  "Total" numeric);
create table dbo."BuiltResourceLines" (
  "BuiltResourceId" bigint references dbo."BuiltResources"("Id"), 
  "Total" numeric);
insert into dbo."BuiltResources"("Total") 
  values (0),(0),(0),(0),(0);
insert into dbo."BuiltResourceLines"("BuiltResourceId","Total") 
  values (1,1),(1,2),(1,3),(2,4),(2,5),(2,6),(3,-7);

UPDATE dbo."BuiltResources" BR
SET "Total" = 
        (
            SELECT coalesce(SUM(BRL."Total"),0)
            FROM dbo."BuiltResourceLines" BRL 
            WHERE BRL."BuiltResourceId" = BR."Id"
        )
returning *;

-- Id | Total
------+-------
--  1 |     6
--  2 |    15
--  3 |    -7
--  4 |     0
--  5 |     0

为了避免每次都更新整个表,您可以只将匹配NEW的行作为目标。

CREATE OR REPLACE FUNCTION update_builtresource_total()
RETURNS TRIGGER LANGUAGE PLPGSQL AS $$
BEGIN
IF TG_OP = 'UPDATE' THEN
        UPDATE dbo."BuiltResources" BR
        SET "Total" = (
        (
            SELECT coalesce(SUM(BRL."Total"),0)
            FROM dbo."BuiltResourceLines" BRL 
            WHERE BRL."BuiltResourceId" = BR."Id"
        )
        WHERE BR."Id"=NEW."BuiltResourceId";
    END IF;
    RETURN NULL;
END $$;

相关问题