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.
Related
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"
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();
The code below is my code to create trigger function to change column "pass".
create or replace function change_pass()
returns trigger as
$$
begin
NEW.pass := 'XXXXXXXXX';
return NEW;
end
$$
language plpgsql;
create trigger change_pass
AFTER insert or update on "D_ACCOUNT"
for each row execute procedure change_pass();
When i called insert, i did not see any changes in my data.
Can anyone explain to me where i was wrong?
You need a BEFORE trigger to change values in the NEW record:
create trigger change_pass
BEFORE insert or update on "D_ACCOUNT"
for each row execute procedure change_pass();
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?
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.