使用触发器的PostgreSQL聚合相关值

发布于 2025-02-13 19:51:51 字数 2928 浏览 0 评论 0原文

我有一个代表薪资系统的数据库。 每个薪资与几个 payrollrows (对M关系为1)有关,并包括一个字段,汇总了其相关的Payrollrows字段。

简而言之,付款包括一个名为“金额的”字段,该字段是其相关 payrollrow 记录的“ paybackeur”字段的总和。

我正在尝试创建一个触发函数,该功能会在创建工资单时自动完成金额的字段。 (的确,它将直接使用其Payrollrow创建)

我已经做到了:

-- Generate the trigger function
CREATE OR REPLACE TRIGGER new_payroll_creation  
 AFTER INSERT  
 ON "Payroll"
 FOR EACH ROW  
 EXECUTE PROCEDURE populate_payroll_amountEur();  

对于该功能,我尝试了此功能,但没有任何成功。

CREATE OR REPLACE FUNCTION populate_payroll_amounteur()  
  RETURNS TRIGGER   
  LANGUAGE PLPGSQL  
  AS  
$$  
BEGIN  
         UPDATE "Payroll"  
        
         SET "amountEurToPay" =  (   SELECT SUM("paybackEur") 
                                     FROM "PayrollRow"
                                     WHERE "payrollId" = NEW."id")
         WHERE ("id" = NEW."id");  
RETURN NEW;  
END;  
$$

有关额外的信息,我的模式看起来像是

model PayrollRow {
  id            Int       @id @default(autoincrement())
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  paybackEur    Decimal   @default(0) @db.Decimal(10, 2)
  payroll       Payroll   @relation(fields: [payrollId], references: [id])
  payrollId     Int
}

model Payroll {
  id             Int           @id @default(autoincrement())
  createdAt      DateTime      @default(now())
  updatedAt      DateTime      @updatedAt
  amountEurToPay Decimal       @default(0) @db.Decimal(10, 2)
  payrollRow     PayrollRow[]
}

您可以为我提供一些支持以实现这一目标吗? :)

更新 - 例如,这起作用(具有ID 2的薪水2),例如,我有点困惑:

CREATE OR REPLACE FUNCTION populate_payroll_amounteur()  
  RETURNS TRIGGER   
  LANGUAGE PLPGSQL  
  AS  
$$  
BEGIN  
         UPDATE "Payroll"  
        
         SET "amountEurToPay" =  (   SELECT SUM("paybackEur") 
                                     FROM "PayrollRow"
                                     WHERE "payrollId" = 2)
         WHERE ("id" = NEW."id");  
RETURN NEW;  
END;  
$$

----更新Mitko 如果您请求架构定义,则实际上我会使用Prisma.io Orm,这为我简化了模式的创建。 一些逆向工程会提供这样的东西:

-- CreateTable
CREATE TABLE "Payroll" (
    "id" SERIAL NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,
    "amountEurToPay" DECIMAL(10,2) NOT NULL DEFAULT 0,

    CONSTRAINT "Payroll_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "PayrollRow" (
    "id" SERIAL NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,
    "paybackEur" DECIMAL(10,2) NOT NULL DEFAULT 0,
    "payrollId" INTEGER NOT NULL,

    CONSTRAINT "PayrollRow_pkey" PRIMARY KEY ("id")
);

    -- AddForeignKey
    ALTER TABLE "PayrollRow" ADD CONSTRAINT "PayrollRow_payrollId_fkey" FOREIGN KEY ("payrollId") REFERENCES "Payroll"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

I have a database representing a payroll system.
Each Payroll is related to several PayrollRows (1 to M relationship), and includes a field summarizing its related payrollRows fields.

Simply said, Payroll includes a field called "amountEurToPay" which is the sum of the "paybackEur" fields of its related PayrollRow records.

I am trying to create a trigger function that automatically completes the amountEurToPay field when a Payroll is created. (indeed it will be created directly with its payrollRow)

I have done this :

-- Generate the trigger function
CREATE OR REPLACE TRIGGER new_payroll_creation  
 AFTER INSERT  
 ON "Payroll"
 FOR EACH ROW  
 EXECUTE PROCEDURE populate_payroll_amountEur();  

For the function, I tried this, but without any success.

CREATE OR REPLACE FUNCTION populate_payroll_amounteur()  
  RETURNS TRIGGER   
  LANGUAGE PLPGSQL  
  AS  
$  
BEGIN  
         UPDATE "Payroll"  
        
         SET "amountEurToPay" =  (   SELECT SUM("paybackEur") 
                                     FROM "PayrollRow"
                                     WHERE "payrollId" = NEW."id")
         WHERE ("id" = NEW."id");  
RETURN NEW;  
END;  
$

For extra information, my schema looks like this

model PayrollRow {
  id            Int       @id @default(autoincrement())
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  paybackEur    Decimal   @default(0) @db.Decimal(10, 2)
  payroll       Payroll   @relation(fields: [payrollId], references: [id])
  payrollId     Int
}

model Payroll {
  id             Int           @id @default(autoincrement())
  createdAt      DateTime      @default(now())
  updatedAt      DateTime      @updatedAt
  amountEurToPay Decimal       @default(0) @db.Decimal(10, 2)
  payrollRow     PayrollRow[]
}

Could you please provide me some support to achieve that? :)

UPDATE--
It seems that that this works (with a preexisting payroll with id 2) for example, I am a bit confused :

CREATE OR REPLACE FUNCTION populate_payroll_amounteur()  
  RETURNS TRIGGER   
  LANGUAGE PLPGSQL  
  AS  
$  
BEGIN  
         UPDATE "Payroll"  
        
         SET "amountEurToPay" =  (   SELECT SUM("paybackEur") 
                                     FROM "PayrollRow"
                                     WHERE "payrollId" = 2)
         WHERE ("id" = NEW."id");  
RETURN NEW;  
END;  
$

---- UPDATE for MiTKo
If you request the schema definition , actually I use prisma.io ORM , which simplified for me the creation of the schema.
Some reverse engineering would give something like this :

-- CreateTable
CREATE TABLE "Payroll" (
    "id" SERIAL NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,
    "amountEurToPay" DECIMAL(10,2) NOT NULL DEFAULT 0,

    CONSTRAINT "Payroll_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "PayrollRow" (
    "id" SERIAL NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,
    "paybackEur" DECIMAL(10,2) NOT NULL DEFAULT 0,
    "payrollId" INTEGER NOT NULL,

    CONSTRAINT "PayrollRow_pkey" PRIMARY KEY ("id")
);

    -- AddForeignKey
    ALTER TABLE "PayrollRow" ADD CONSTRAINT "PayrollRow_payrollId_fkey" FOREIGN KEY ("payrollId") REFERENCES "Payroll"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

泛泛之交 2025-02-20 19:51:53

尝试一下(它正在用于更新和删除)

        -- Generate the trigger function
    CREATE OR REPLACE TRIGGER new_payroll_creation  
     AFTER INSERT  or UPDATE or delete
     ON "PayrollRow"
     FOR EACH ROW  
     EXECUTE PROCEDURE populate_payroll_amountEur();  
     
    
     
    
CREATE OR REPLACE FUNCTION populate_payroll_amounteur()  
  RETURNS TRIGGER   
  LANGUAGE PLPGSQL  
  AS  
$  
BEGIN  
     UPDATE "Payroll"         
     SET "amountEurToPay" =  
     ( 
      SELECT COALESCE(SUM("paybackEur") ,0)
      FROM "PayrollRow"
      WHERE "payrollId" = COALESCE( NEW."payrollId",OLD."payrollId")
     )
     WHERE ("id" = (COALESCE( NEW."payrollId",OLD."payrollId")));  
RETURN NEW;  
END;  
$

Try this (it's working for update and delete as well)

        -- Generate the trigger function
    CREATE OR REPLACE TRIGGER new_payroll_creation  
     AFTER INSERT  or UPDATE or delete
     ON "PayrollRow"
     FOR EACH ROW  
     EXECUTE PROCEDURE populate_payroll_amountEur();  
     
    
     
    
CREATE OR REPLACE FUNCTION populate_payroll_amounteur()  
  RETURNS TRIGGER   
  LANGUAGE PLPGSQL  
  AS  
$  
BEGIN  
     UPDATE "Payroll"         
     SET "amountEurToPay" =  
     ( 
      SELECT COALESCE(SUM("paybackEur") ,0)
      FROM "PayrollRow"
      WHERE "payrollId" = COALESCE( NEW."payrollId",OLD."payrollId")
     )
     WHERE ("id" = (COALESCE( NEW."payrollId",OLD."payrollId")));  
RETURN NEW;  
END;  
$
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文