How to print NEW value with trigger Postgres - sql

I want to create trigger for Insert operation, and procedure that prints inserted value.
CREATE TRIGGER added_product_info_trigger
BEFORE INSERT
ON products
EXECUTE PROCEDURE added_product_info();
And my procedure
CREATE OR REPLACE FUNCTION added_product_info()
RETURNS trigger
AS
$$
(Select p.productname, s.companyname from products as p, suppliers as s
where p.supplierid = s.supplierid)
$$ LANGUAGE SQL;
How can I print my inserted value?

Sql functions cannot return trigger. You probably wanted to write a plpgsql function.
A trigger function cannot generate any output (like results of a select query).
You can use raise notice to pass some results to the client program:
create or replace function added_product_info()
returns trigger as $$
declare
company text;
begin
select companyname
from suppliers
where supplierid = new.supplierid
into company;
raise notice 'inserted: "%" supplied by "%"', new.productname, company;
return new;
end;
$$ language plpgsql;
The record new is visible in a trigger function only if the trigger is declared for each row
(default is for each statement when records new and old are not accessible):
create trigger added_product_info_trigger
before insert on products
for each row
execute procedure added_product_info();
If a trigger is before insert for each row it must return new.
Note that the client must be ready to get and process the notice.
If you run the query in the standard psql shell program, you ll get:
insert into products values ('some product', 1);
NOTICE: inserted: "some product" supplied by "company"
INSERT 0 1
Read:
Overview of Trigger Behavior
Visibility of Data Changes
Trigger Procedures

Related

Search in 3 tables using PL/pgSQL functions and triggers

I am new to SQL and still learning functions and triggers.
I have 3 tables:
PRODUCTS_BOUGHT
CUSTOMER
DATE
PRODUCTS
3FG
2022-12-15
25
4HZ
2022-12-18
30
PRODUCTS_PRICE:
DATE
TYPE
PRICE
2022-12-15
A
125$
2022-12-18
B
147$
CUSTOMERS_REGISTER:
CUSTOMER
TYPE
3FG
A
4HZ
B
I need to add a column "COST" in the REF table with a value obtained using: COST = PRICE * PRODUCTS. But the function needs to check that the price is applied based on the type of product purchased by the customer in that certain date to obtain something like this:
PRODUCTS_BOUGHT
CUSTOMER
DATE
PRODUCTS
COST
3FG
2022-12-15
25
3125
4HZ
2022-12-18
30
4410
I need to use something like the following:
ALTER TABLE products_bought
ADD COLUMN cost;
CREATE OR REPLACE FUNCTION calc_cost()
RETURNS TRIGGER AS $$
BEGIN
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER cost_trigger
BEFORE INSERT OR UPDATE ON products_bought
FOR EACH ROW
EXECUTE FUNCTION calc_cost();
I have been trying creating the column first and then adding the value like this:
ALTER TABLE products_bought
ADD COLUMN cost;
CREATE OR REPLACE FUNCTION calc_cost()
RETURNS TRIGGER AS $$
BEGIN
SELECT(products_bought.products * products_price.price) INTO cost
FROM products_bought, products_price, customers_register
WHERE products_bought.rf_date = products_price.fp_date AND
customers_register.type = customers_register.type;
RETURN cost;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER cost_trigger
BEFORE INSERT OR UPDATE ON products_bought
FOR EACH ROW
EXECUTE FUNCTION calc_cost();
Selecting from the table products_bought in your trigger function looks like a misunderstanding. The trigger is fired BEFORE INSERT OR UPDATE ON products_bought, so just work with the special NEW record. And make sure you also RETRUN NEW;:
CREATE OR REPLACE FUNCTION calc_cost()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
SELECT INTO NEW.cost
NEW.products * p.price
FROM products_price p
WHERE p.fp_date = NEW.rf_date;
RETURN NEW;
END
$func$;
This only makes sense if there is a single matching row in table products_price. If there can be more, you have to define which row to pick. If there is none, cost will not be assigned.
I also removed the table customers_register from the query, since it didn't seem to do anything useful (unless you wanted to nullify cost if there is no related row in that table, which I doubt.)
Related:
PostgreSQL Update trigger
The returning trigger function should return the NEW instead of only the column affected.
notice that the insert into is also beign inserted at the NEW.cost value.
You can look here : PostgreSQLTriggers for trigger default values like NEW , OLD from the row it is beign edited.
CREATE OR REPLACE FUNCTION calc_cost()
RETURNS TRIGGER AS $$
BEGIN
SELECT(products_bought.products * products_price.price) INTO NEW.cost
FROM products_bought, products_price, customers_register
WHERE products_bought.rf_date = products_price.fp_date AND
customers_register.type = customers_register.type;
RETURN NEW.*;
END;
$$ LANGUAGE plpgsql;

PostgeSQL trigger before insert unique value

Is there any variant to create a trigger before insert and if the value is a value that exists already in table, just update it. I know about 'ON DUBLICATE KEY' or a 'ON CONFLICT' in PostgreSQL but I need a trigger just because it's a task in my university.
I tried to create it, but I get just an error about duplicate keys.
CREATE or replace FUNCTION trigger_function()
RETURNS TRIGGER
LANGUAGE PLPGSQL
AS $$
BEGIN
IF new.name in (select name from "Test")
then
update "Test" set intt = new.intt where name = new.name;
end if ;
return new;
END;
$$
CREATE TRIGGER trigger_name
BEFORE insert
ON "Test"
for each row
EXECUTE PROCEDURE trigger_function();
Is it possible to create such trigger?
Read the docs plpgsql trigger function:
Row-level triggers fired BEFORE can return null to signal the trigger manager to skip the rest of the operation for this row (i.e., subsequent triggers are not fired, and the INSERT/UPDATE/DELETE does not occur for this row).
So RETURN NULL after the UPDATE statement inside the if andRETURN NEW when the if is false. Then the INSERT will happen if the name is unique.

Move Data from One table to other table by using trigger in postgreSQL

I have the requirement to move data from one table to another table when the value of one of the columns is updated. And I just want to move the updated row to the new table.
Below is my trigger that I have written. The issue with my code is, that it is moving all the data and not just the row which was updated. Can anyone give a suggestion?
create or replace function moveToAC1ControlHist()
returns trigger as $$
begin if NEW.file_status='CO'
then
insert into ac1_control_hist (file_status,identitifier)
(
select file_status,identitifier
from
ac1_control where new.FILE_STATUS = 'CO'
);
end if;
return new;
end;
$$ language plpgsql;
create TRIGGER AC1_CONTROL_TRIGGER AFTER update of file_status ON AC1_CONTROL
FOR EACH ROW when (new.file_status ='CO')EXECUTE PROCEDURE moveToAC1ControlHist();
I think the logic you want is:
create or replace function moveToAC1ControlHist()
returns trigger as
$$
begin
insert into ac1_control_hist (file_status,identitifier)
values (new.file_status, new.identitifier);
return null;
end;
$$ language plpgsql;
create trigger ac1_control_trigger
after update of file_status on ac1_control
for each row
when (new.file_status ='co')
execute function movetoac1controlhist()
;
Rationale:
you just want to copy (part of) the row being updated, so there is no need to select; you can access the values of the current row with new in a row-level trigger
the trigger definition filters on new file_status that is equal to 'CO', so there is no need for a if construct in the function
this is an after trigger, so you can just return null - the result is discarded anyway

PostgreSQL Create Trigger which runs a function on every insert or update of a table

I have defined two tables, scores and analyzed_avg_score, in my postgres database. I also have a function which i declaired like that:
CREATE FUNCTION updateAvgScore() RETURNS void AS $$
INSERT into analyzed_avg_score
(SELECT
user,
avg(score_value)
FROM
scores
group by user) on conflict do nothing;
$$ LANGUAGE SQL;
Now, I want to have a trigger or something similar that runs this function every time I insert or update something in score. I don't have a lot of experience with SQL, yet. So, does anyone have an idea how the trigger should look like?
CREATE TRIGGER SCORE_INSERT AFTER INSERT ON SCORE
FOR EACH ROW EXECUTE PROCEDURE updateAvgScore();
/*Have it return a trigger like this */
CREATE OR REPLACE FUNCTION updateAvgScore() RETURNS TRIGGER AS $example_table$
BEGIN
/*YOUR lOGIC HERE*/
END;
$example_table$ LANGUAGE plpgsql;

Update error in postgres SQL

CREATE TRIGGER INSERT_salesorderdetail
before insert on salesorderdetail
for each row
UPDATE customer
set number_of_items=IFNULL(number_of_items,0)+1
where new.customerid=customer.customerid;
I have 2 tables salesorderdetail and customer and i want each time i inserts a new item in salesorderdetail to update my columne in customer the number_of_items but for some reason i get a syntax error in update.
This might help you:
CREATE OR REPLACE FUNCTION update_customer()
RETURNS trigger AS
$BODY$
-- update ur table here
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update_customer()
OWNER TO db_name;
Now create trigger as:
CREATE TRIGGER INSERT_salesorderdetail
before insert on salesorderdetail
for each row execute procedure update_customer();