SQL function, substract variable on another table when insert data - sql

I have a relational database:
Examination (ExaminationID, DetectedDisease, Name)
Uses (ReagentID, ExaminationID, ReagentQuantity)
Reagent (ReagentID, Name, Stock, MinimumPermissibleStock)
Examined (InsuranceNumber, ExaminationID, ExaminationDate, Results, TakenResults?)
I want to create a function that when a new record of "examined" is added the quantity of the reagent that examination uses to be substracted from "reagent.stock". Also when reagent.minimumPermissibleStock is lower than stock to return a warning message.
For the second part of the problem i tried this, but it does not work:
create function warning() returns trigger AS $warning$
begin
if reagent.new.stock < reagent.minimumPermissibleStock then
raise exception 'Probably mistake';
end if;
return new;
end;
$warning$ LANGUAGE plpgsql;
Thanks in advance
EDIT
I tried that one but still it doesnt work:
CREATE FUNCTION log_examination2() RETURNS trigger AS $$
DECLARE
examID integer;
BEGIN
BEGIN
INSERT INTO examination (detecteddisease, ename) VALUES('disease1', 'name') RETURNING examinationID INTO examID;
INSERT INTO Uses VALUES(reagentID, examID, reagentQuantity);
UPDATE Reagent SET Stock = Stock - reagentQuantity WHERE ReagentID = reagentID;
RETURN new;
END;
END;
$$ LANGUAGE plpgsql VOLATILE;
CREATE TRIGGER validate_quantity AFTER UPDATE OF Stock ON Reagent EXECUTE PROCEDURE log_examination2();

Triggers can only operate on the table/view to which they are attached--hence the error (I'm assuming you created the trigger as an AFTER UPDATE on Examined).
To actually solve the problem, what you want to do is create a transaction to represent the entire set of operations, and then attach the above function as a trigger AFTER UPDATE to Reagent.
For example:
CREATE FUNCTION log_examination(int reagentID, int reagentQuantity) AS $$
BEGIN
BEGIN;
examID := INSERT INTO Examination VALUE("disease1", "name") RETURNING ExaminationID;
INSERT INTO Uses VALUE(reagentID, examID, reagentQuantity);
UPDATE Reagent SET Stock = Stock - reagentQuantity WHERE ReagentID = reagentID;
COMMIT;
END;
$$ LANGUAGE plpgsql;
and
CREATE TRIGGER validate_quantity AFTER UPDATE OF Stock ON Reagent EXECUTE PROCEDURE warning();

Related

PostgreSQL Trigger update all row in the same table

I want calculate a field when update one or two fields but Trigger calculate all table's row with same value, not only the row updated. What is wrong ..? Thank you.
Create or Replace Function hospital_ocupation() returns Trigger
as
$$
Begin
update hospital set p_ocupation = (new.n_cases*100)/new.capacity
where old.n_case <> new.n_case;
return new;
End
$$
language plpgsql;
Create Trigger update_ocupation after update on hospital
for each row
WHEN (pg_trigger_depth() = 0)
execute procedure hospital_ocupation();
update hospital set capacity=500,n_cases=50
where id_hospital = 1
enter image description here
Don't use UPDATE, assign the calculated value to the new record in a BEFORE trigger:
create or replace function hospital_ocupation()
returns trigger
as
$$
begin
new.p_ocupation := (new.n_cases*100)/new.capacity;
return new;
End
$$
language plpgsql;
To make that work you need a BEFORE trigger:
create trigger update_ocupation
BEFORE update on hospital
for each row
WHEN (old.n_case <> new.n_case)
execute procedure hospital_ocupation();

How to send current schema and affected table with notification function/trigger?

When a row is inserted or updated in a specific table (in this example it's the table called 'fpl'). How can I include the affected table and schema in the notification?
SQL as follows:
CREATE TRIGGER fpl_event
AFTER INSERT OR UPDATE ON fpl
FOR EACH ROW
EXECUTE PROCEDURE fpl_notify();
CREATE OR REPLACE FUNCTION fpl_notify()
RETURNS trigger AS $$
BEGIN
NOTIFY dbNotification, 'something got insereted in fpl!';
RETURN NULL;
END;
$$ LANGUAGE PLPGSQL;
Update:
CREATE OR REPLACE FUNCTION fpl_notify() RETURNS trigger
AS
$$
BEGIN
EXECUTE format('notify dbNotification, ''%s''', TG_TABLE_SCHEMA);
RETURN NULL;
END;
$$ LANGUAGE PLPGSQL;
read trigger special variables

Trigger for update timestamp field

I'm trying to create trigger, that updates my lastmodified field on insert/update. Here's my trigger:
CREATE OR REPLACE TRIGGER timestamp_trigger BEFORE INSERT OR UPDATE ON orders
FOR EACH ROW EXECUTE PROCEDURE timestamp_update;
and my procedure:
CREATE OR REPLACE FUNCTION timestamp_update()
RETURNS TRIGGER
AS
$$
BEGIN
UPDATE orders
SET lastmodified = getdate()
WHERE orderid = new.orderid
RETURN new;
END;
$$ language plpgsql;
Unfortunately when I try to update some field, field isn't updated. Also when i create row, the lastmodified field isn't updated.
Do not use update in a trigger like this because it may lead to endless recursive loop.
If you want to modify inserted/updated row, just change the new record:
CREATE OR REPLACE FUNCTION timestamp_update()
RETURNS TRIGGER
AS
$$
BEGIN
NEW.lastmodified = now();
RETURN new;
END;
$$ language plpgsql;
The syntax create or replace trigger is incorrect.
CREATE TRIGGER timestamp_trigger
BEFORE INSERT OR UPDATE ON orders
FOR EACH ROW EXECUTE PROCEDURE timestamp_update();

PL/PgSQL creating a conditional trigger on insert

I'm working on my first ever Trigger. When I'm doing an INSERT on table I want to conditionaly remove rows from other table.
Here is a trigger:
CREATE OR REPLACE FUNCTION clear_seen_by()
RETURNS trigger AS
$BODY$
BEGIN
IF (OLD.popup = '1') THEN
DELETE FROM news_seen_by;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Invoked by:
CREATE TRIGGER clear_seen_by
AFTER INSERT
ON news
FOR EACH STATEMENT
EXECUTE PROCEDURE clear_seen_by();
As an error I see that NEW or OLD (if I motify the trigger) is not declared/unknown. Where is the problem?
In an INSERT statement you do not have an OLD record defined.
You should use NEW.popup instead, and also declare the trigger to be FOR EACH ROW.
CREATE OR REPLACE FUNCTION clear_seen_by() RETURNS trigger AS
$BODY$
BEGIN
IF (NEW.popup = '1') THEN
DELETE FROM news_seen_by;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
CREATE TRIGGER
clear_seen_by
AFTER INSERT ON
news
FOR EACH ROW EXECUTE PROCEDURE
clear_seen_by();
You declare a trigger FOR EACH STATEMENT. Maybe you need FOR EACH ROW?
FOR EACH STATEMENT triggers do not have NEW and OLD.

Trigger Not Executing Yet It's Created

I have a trigger function I'm trying to have execute in Postgres.
It compiles and adds the trigger, however it does not insert the value into the table as I had hoped.
The function it uses looks like this:
CREATE OR REPLACE FUNCTION
calc_gnpDifference(n integer, o integer)
RETURNS NUMERIC AS $$
SELECT $1 ::numeric - $2::numeric AS gnpDifference;
$$ LANGUAGE SQL;
And the Trigger part:
CREATE OR REPLACE FUNCTION autoCalculate() RETURNS TRIGGER AS $$
BEGIN
IF NEW.gnp_old > NEW.gnp_old THEN
NEW.gnpDifference := calc_gnpDifference(NEW.gnp_old, NEW.gnp);
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER insertDifference ON country;
CREATE TRIGGER insertDifference BEFORE INSERT ON country
FOR EACH ROW EXECUTE PROCEDURE autoCalculate();
However, when I insert data, the trigger does not update the gnpDifference field as I had hoped. Thoughts on why this might be happening?
Obviously this condition: IF NEW.gnp_old > NEW.gnp_old will never be true so the trigger will never have any effect.