Postgresql trigger not update - stack depth limit reached [duplicate] - postgresql

This question already has an answer here:
Trigger to update a column on update
(1 answer)
Closed 11 months ago.
everyone!
i want to do a very simple trigger that sees if some conditionals are 0 they set false on the same table, buy i am doing wrong and it s not updating
CREATE or REPLACE FUNCTION chequeo_datos() RETURNS trigger AS $$
BEGIN
IF NEW.val_cuota = 0 or NEW.val_pat = 0 THEN
UPDATE habitat SET status=False;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER chequeo_datos AFTER INSERT OR UPDATE ON public.habitat
FOR EACH ROW EXECUTE FUNCTION chequeo_datos();
it gives me this error : "stack depth limit reached".
could you tell me what i am doing wrong?

Don't UPDATE the table, assign the new value to the record's column:
CREATE or REPLACE FUNCTION chequeo_datos() RETURNS trigger AS $$
BEGIN
IF NEW.val_cuota = 0 or NEW.val_pat = 0 THEN
new.status := False;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
For that to work, you need a BEFORE trigger:
CREATE TRIGGER chequeo_datos
BEFORE INSERT OR UPDATE ON public.habitat
FOR EACH ROW EXECUTE FUNCTION chequeo_datos()

Related

Build a trigger that avoids to update the values of one column

I have a table in PostgretSQL. I want to build a trigger that avoids to update colb1 column. This column has five alternatives: Rea, Can, Loa, Mul, Alm. So the trigger doesn't let upload values from Rea to Can.
I've built this function but this is fail.
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS trigger AS
$BODY$
BEGIN
new.colb1.tabl1 = 'Rea' := old.colb1.tabl1 = 'Can';
new.colb1.tabl1 = 'Can' := old.colb1.tabl1 = 'Rea';
RETURN new;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
DROP TRIGGER IF EXISTS trigger_name ON table1;
CREATE TRIGGER trigger_name BEFORE UPDATE ON table1
FOR EACH ROW EXECUTE PROCEDURE example_trigger();
I edited my post with changes:
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS TRIGGER AS
$$
BEGIN
NEW.colb1 := OLD.colb1;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER not_changes
BEFORE UPDATE
ON tabl1
FOR EACH ROW
EXECUTE PROCEDURE example_trigger();
It's not exactly that I want because I want that the values Loa, Mul and Alm can be update.
A slight modification of your function to stop the modification of colb1 from Rea or Can to Can or Rea.
CREATE OR REPLACE FUNCTION example_trigger()
RETURNS TRIGGER AS
$$
BEGIN
IF OLD.colb1 in ('Rea', Can') AND NEW.colb1 IN ('Rea', 'Can') THEN
NEW.colb1 := OLD.colb1;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
This will not stop a user from using an intermediate UPDATE to change to one of Loa/Mul/Alm and then to either Rea or Can

Trigger PostgreSQL to update one value based on the sum of three others

I am trying to make a boolean become true when the sum of three integers is equal to 100 and false when the sum is not equal to 100.
I am making a trigger function in Postgres to do that, but getting the following error:
ERROR: «db_fondos.checksize» is not a known variable
LINE 6: DB_Fondos.CheckSize=true;
I hope you could help me.
Code:
CREATE FUNCTION check_sum()
RETURNS TRIGGER
AS $$
BEGIN
IF DB_Fondos.SizeLarge+DB_Fondos.SizeMid+DB_Fondos.SizeSmall=100 then
DB_Fondos.CheckSize=true;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
Why not simply use a computed column for this instead of a trigger? The database manages the computation for you under the hood and you get an always up-to-date value when you query the table:
create table DB_Fondos (
...
SizeLarge int,
SizeMid int,
SizeSmall int,
check_sum boolean generated always as (
coalesce(SizeLarge, 0)
+ coalesce(SizeMid, 0)
+ coalesce(SizeSmall, 0) = 100
)
);
In a trigger, you relate to the newly inserted line with NEW, not with the table name:
CREATE FUNCTION check_sum()
RETURNS TRIGGER
AS $$
BEGIN
IF NEW.SizeLarge + NEW.SizeMid + NEW.SizeSmall = 100 THEN
NEW.CheckSize = true;
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;

How to avoid recursion in an update trigger that does an update?

I need to update the vat_total_sum of goods in a record using a trigger. But the trigger fires to update the record and falls into recursion. How can I avoid this?
The code:
CREATE OR REPLACE FUNCTION vat_total_sum() RETURNS TRIGGER AS $$
BEGIN
UPDATE goods SET vat_total_sum = NEW.vat_sum / 100 * NEW.vat_percent
WHERE goods_id = new.goods_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER vat_total_sum AFTER INSERT OR UPDATE ON goods
FOR EACH ROW EXECUTE PROCEDURE vat_total_sum();
Don't use UPDATE, use a BEFORE triger and assign the new value:
CREATE OR REPLACE FUNCTION vat_total_sum() RETURNS TRIGGER AS $$
BEGIN
new.vat_total_sum := NEW.vat_sum / 100 * NEW.vat_percent;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER vat_total_sum
BEFORE INSERT OR UPDATE ON goods
FOR EACH ROW EXECUTE PROCEDURE vat_total_sum();

postgresql - trigger function with condition

I'm trying to create a trigger with a condition. Based on the geom length I want the attribute "nom" (= name) to be written in upper case or lower case.
here's what I have:
CREATE OR REPLACE FUNCTION public.test_upper_lower()
RETURNS trigger AS
$BODY$
BEGIN
NEW.dummy:= (ST_Length(new.geom));
if (SELECT dummy FROM ligne_ligne)>100
then NEW.nom:= LOWER(nom) FROM ligne_ligne;
else NEW.nom:= UPPER(nom) FROM ligne_ligne;
end if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
DROP trigger IF EXISTS test_upper_lower on public.ligne_ligne;
CREATE trigger test_upper_lower BEFORE INSERT OR UPDATE on public.ligne_ligne
FOR EACH ROW
EXECUTE PROCEDURE public.test_upper_lower();
With this I have a "more than one row returned by a subquery" error
Based on other questions on this forum I tried it using case instead of if and using when in the trigger itself not the function but neither are working
Any ideas ?
Thanks
You don't need (or can actually) use SELECT statements to access data from the inserted row.
The part SELECT dummy FROM ligne_ligne returns all rows from that table - not just from the one relevant to the trigger.
As you just want to check the value you just calculated, simply use new.dummy at that point:
CREATE OR REPLACE FUNCTION public.test_upper_lower()
RETURNS trigger AS
$BODY$
BEGIN
NEW.dummy:= ST_Length(new.geom);
if new.dummy > 100 then --<< no SELECT necessary
NEW.nom:= LOWER(new.nom); --<< no "FROM", just access the value
else
NEW.nom:= UPPER(new.nom);
end if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;

Postgresql Trigger example

I created a trigger when a row updated trigger will change that row. When I update a column I get an error. How can I solve?
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
CREATE OR REPLACE FUNCTION ynt_call()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'UPDATE' THEN
UPDATE ynt.a_test SET date_time = now();
END IF;
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_call AFTER UPDATE ON ynt.a_test FOR EACH ROW EXECUTE PROCEDURE ynt_call();
Of course you're looping until the end of time, because you are updating row when updating row. You should set the field date_time using the special variable new as following:
CREATE OR REPLACE FUNCTION ynt_call()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'UPDATE' THEN
new.date_time = now();
END IF;
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_call AFTER UPDATE ON ynt.a_test FOR EACH ROW EXECUTE PROCEDURE ynt_call();