Postgres cannot replace trigger - postgresql

I am trying to create a function to automatically create a row in one table when there is an insert in another row, I already created it before but it was wrong and now I can't create it again
this is my sql code
create or replace function public.handle_new_user()
returns trigger as
$$
begin
insert into public.profiles (user_id, first_name, last_name)
values (new.id, new.raw_user_meta_data->>'first_name', new.raw_user_meta_data->>'last_name');
return new;
end;
$$
language plpgsql security definer;
create or replace trigger on_auth_user_created
after insert on auth.users
for each row
execute procedure public.handle_new_user();
I am getting this error
Failed to validate sql query: syntax error at or near "trigger"

Related

Creating trigger for every new insertion in postgresql

I have two table table1 and table2 in two different database. Now I have created a trigger which will insert in table2 whenever a new row is inserted in table1. Below is my trigger
CREATE TRIGGER sync_user_table AFTER INSERT ON table1
for each row execute procedure sync_and_maintain_users_table()
CREATE OR REPLACE function sync_and_maintain_users_table()
returns trigger as
$BODY$
begin
insert into global_db.public.table2
values (user_uuid, user_registration_date, user_service_provider);
end;
$BODY$
language plpgsql;
But the above trigger is not working. Neither I am getting any errors, I am not sure what's wrong.
You may have no error when creating the trigger but you likely have errors at run-time:
CREATE OR REPLACE function sync_and_maintain_users_table()
returns trigger as
$BODY$
begin
insert into global_db.public.table2
values (user_uuid, user_registration_date, user_service_provider);
end;
$BODY$
language plpgsql;
CREATE FUNCTION
CREATE TRIGGER sync_user_table AFTER INSERT ON table1
for each row execute procedure sync_and_maintain_users_table();
CREATE TRIGGER
insert into table1 values(1);
ERROR: cross-database references are not implemented: "global_db.public.table2"
LINE 1: insert into global_db.public.table2
^
QUERY: insert into global_db.public.table2
values (user_uuid, user_registration_date, user_service_provider)
CONTEXT: PL/pgSQL function sync_and_maintain_users_table() line 3 at SQL statement
In PostgreSQL you cannot reference directly another database with database.schema.object syntax.
And if you fix this you have another error:
CREATE OR REPLACE function sync_and_maintain_users_table()
returns trigger as
$BODY$
begin
insert into public.table2
values (user_uuid, user_registration_date, user_service_provider);
end;
$BODY$
language plpgsql;
CREATE FUNCTION
insert into table1 values(1);
ERROR: column "user_uuid" does not exist
LINE 2: values (user_uuid, user_registration_date, user_service_...
^
HINT: There is a column named "user_uuid" in table "table2", but it cannot be referenced from this part of the query.
QUERY: insert into public.table2
values (user_uuid, user_registration_date, user_service_provider)
CONTEXT: PL/pgSQL function sync_and_maintain_users_table() line 3 at SQL statement
You need to add code to initialize variables used in VALUES clause.
See examples in https://www.postgresql.org/docs/12/plpgsql-trigger.html.

Updating current timestamp of multiple tables through single trigger function

I have 2 tables created :- Table Banks and Branch. Both the tables have column last_updated(which means when was the record last updated.) I have created after update trigger for each row on both the tables. The trigger and trigger function looks like below :-
create trigger banks_upd_trg
after update of phone_no
on Banks
FOR EACH ROW
EXECUTE PROCEDURE bankdetails_upd();
create trigger branch_upd_trg
after update of email_address
on Branch
FOR EACH ROW
EXECUTE PROCEDURE bankdetails_upd();
create or replace FUNCTION bankdetails_upd()
RETURNS trigger AS
$BODY$
BEGIN
EXECUTE format('update %I.%I SET last_updated=current_timestamp where id=new.id',TG_SHEMA_NAME,TG_TABLE_NAME)
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql
The trigger is getting executed successfully but isn't working at the time of updating phone_no and email_address column in Banks and Branch table respectively.
No need for dynamic SQL or an UPDATE statement.
Use a before trigger and assign the value to the NEW record.
create or replace FUNCTION bankdetails_upd()
RETURNS trigger AS
$BODY$
BEGIN
new.last_updated := current_timestamp;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
create trigger banks_upd_trg
BEFORE update of phone_no
on Banks
FOR EACH ROW
EXECUTE PROCEDURE bankdetails_upd();
create trigger branch_upd_trg
BEFORE update of email_address
on Branch
FOR EACH ROW
EXECUTE PROCEDURE bankdetails_upd();

PL/pgSQL: Update a table using a record

I have an insert trigger in a PostgreSQL 9.5 database which copies the row being inserted to another table:
CREATE OR REPLACE FUNCTION data_record_insert () RETURNS TRIGGER AS $x$
BEGIN
EXECUTE 'INSERT INTO data_record_backup VALUES ($1.*)' USING new;
RETURN new;
END;
$x$ LANGUAGE PLPGSQL;
However, I want to be able to use Postgres' INSERT ... ON CONFLICT upsert statement to insert rows into these tables but can't figure out how to write the trigger. It'd be something like this:
CREATE OR REPLACE FUNCTION data_record_insert () RETURNS TRIGGER AS $x$
BEGIN
EXECUTE 'INSERT INTO data_record_backup VALUES ($1.*)
ON CONFLICT (pk) DO UPDATE SET column_names($1) = $1.*' USING new;
RETURN new;
END;
$x$ LANGUAGE PLPGSQL;
But obviously that SET column_names($1) = $1.* is wrong, it's just something I made up. Is there some way to achieve this?

Postgres trigger that will insert a row into another table before it's deleted

I have a table (entry_table) filled with various geographic location data currently used by clients for our front end Web feature service. If a user deleted their entry in the WFS it is deleted in our postgres database. I would like to create a trigger that will run an INSERT command to copy the row(roughly 25 columns of data) to a second table(historical_entry_table) so if the entries are needed again in the future they can be easily retrieved.
Here's what I have working so far. I'm new to Triggers so I know the syntax is off. Not sure where to go from here. Im running postgres 8.4
In the table :
CREATE TRIGGER trigger_name BEFORE DELETE
ON entry_table
FOR EACH ROW
EXECUTE PROCEDURE trigger_backup_row
The Function itself:
CREATE OR REPLACE FUNCTION trigger_backup_row()
LANGUAGE SQL
RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO historical_entry_table (col1, col2, etc) values (OLD.col1, OLD.col2, OL
RETURN NULL:
END;
$BODY$
I will put a working example here:
CREATE OR REPLACE FUNCTION trigger_backup_row()
RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO PCIcards_backup (MODEL, SUBSYSTEM_DEVICE, ADAPTER, MAPPING) values (NEW.MODEL, NEW.SUBSYSTEM_DEVICE, NEW.ADAPTER, NEW.MAPPING);
RETURN NEW;
END;
$BODY$
language PLPGSQL
As you can see, you only need to set the language at the end of a file with param PLPGSQL because SQL cannot return triggers.
you have just about got it. your code here, updated :
CREATE OR REPLACE FUNCTION trigger_backup_row()
RETURN trigger AS
$BODY$
BEGIN
INSERT INTO historical_entry_table (col1, col2, etc) values (OLD.col1, OLD.col2, OLD.etc);
END;
$BODY$
Posting the correct version of the last answer:
CREATE OR REPLACE FUNCTION trigger_backup_row()
RETURN trigger
LANGUAGE plpgsql
AS
$$
BEGIN
INSERT INTO historical_entry_table (col1, col2, etc) values (OLD.col1, OLD.col2, OLD.etc);
RETURN new;
END;
$$

PostgreSQL 9.3 trigger function to insert into table with parameterized name

I'm trying to dynamically partition log entries in Postgres. I have 53 child tables (1 for each week's worth of log entries), and would like to route INSERTs to a child table using a trigger.
I run the function with INSERT INTO log5 VALUES (NEW.*), and it works.
I run the function with the EXECUTE statement instead, and it fails. Within the EXECUTE statement, it's recognizing NEW as a table name and not a variable passed to the trigger function. Any ideas on how to fix? Thanks!
The error:
QUERY: INSERT INTO log5 VALUES (NEW.*)
CONTEXT: PL/pgSQL function log_roll_test() line 6 at EXECUTE statement
ERROR: missing FROM-clause entry for table "new" SQL state: 42P01
My function:
CREATE FUNCTION log_roll_test() RETURNS trigger AS $body$
DECLARE t text;
BEGIN
t := 'log' || extract(week FROM NEW.updt_ts); --child table name
--INSERT INTO log5 VALUES (NEW.*);
EXECUTE format('INSERT INTO %I VALUES (NEW.*);', t);
RETURN NULL;
END;
$body$ LANGUAGE plpgsql;
My trigger:
CREATE TRIGGER log_roll_test
BEFORE INSERT ON log FOR EACH ROW
EXECUTE PROCEDURE log_roll_test();
CREATE FUNCTION log_roll_test()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('INSERT INTO %I SELECT ($1).*' -- !
, to_char(NEW.updt_ts, '"log"WW')) -- child table name
USING NEW; -- !
RETURN NULL;
END
$func$;
You cannot reference NEW inside the query string. NEW is visible in the function body, but not inside EXECUTE environment. The best solution is to pass values in the USING clause.
I also substituted the equivalent to_char(NEW.updt_ts, '"log"WW') for the table name. to_char() is faster and simpler here.