When I delete an athlete from my database I want to take the sum he has raised and divide the sum between all the other athletes in my database.
When I run my code "addBalance" becomes Null and therefore all the sums become Null but when I run the query outside the function it runs exactly as I want it to. It looks like "old" is causing trouble. Any help is appreciated, thank you.
Here is the code and the tables are below the code.
CREATE OR REPLACE FUNCTION divideMoney()
RETURNS TRIGGER
AS $$
DECLARE athleteSum int;
DECLARE peopleCount bigint;
DECLARE addBalance int;
BEGIN
SELECT sum::INTEGER from People P JOIN Accounts A ON P.ID = A.peopleID
WHERE A.peopleID = old.ID INTO athleteSum;
SELECT COUNT(*) FROM Accounts INTO peopleCount;
RAISE NOTICE 'athleteSum --->%', athleteSum;
RAISE NOTICE 'peopleCount --->%', peopleCount;
addBalance := athleteSum / peopleCount::INTEGER;
RAISE NOTICE 'addBalance --->%', addBalance;
RAISE EXCEPTION 'STOP';
FOR person IN 0..(peopleCount - 1) LOOP
IF person <> old.ID THEN
UPDATE Accounts
SET sum = sum::INTEGER + addBalance
WHERE peopleID = person;
END IF;
END LOOP;
RETURN OLD;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER divedeDeletedMoney
BEFORE DELETE ON People
FOR EACH ROW
EXECUTE PROCEDURE divideMoney();
CREATE TABLE Gender (
gender CHAR(1),
description VARCHAR(10),
PRIMARY KEY (gender)
);
CREATE TABLE People (
ID INT,
name VARCHAR(50),
gender CHAR(1),
height FLOAT,
PRIMARY KEY (ID),
FOREIGN KEY (gender) REFERENCES Gender (gender)
);
CREATE TABLE Accounts (
peopleID int PRIMARY KEY,
sum varchar(255),
last_updated date,
FOREIGN KEY (peopleID) REFERENCES People (id)
);
Best Answer
To have a realistic demo case, you need to populate the tables, not just create them.
Your title says "after deleting a row", but your trigger is clearly a "before" trigger.
If you (attempt to) delete a row from people which has no corresponding entry in accounts, then athleteSum naturally becomes NULL. What else would it do? If you wish to avoid this, you need to take steps to avoid it. Convert to zero? Throw an error? I don't know, only you can know.
You are dividing two integers. The result of integer division is already an integer. No rounding is necessary. Shouldn't it be
(peopleCount-1)
? Otherwise you are distributing the value back to the row that was just (attempted to be) deleted.Why would you expect the peopleID to be densely packed between 0 and peopleCount? Especially since you just attempted to delete one of those intervening values?
For a delete trigger, NEW is NULL. Returning NULL prevents the delete from actually happening. Is that what you want?