Accessing current row values in a trigger - sql

I created a function will insert a value into a json for each row inserted in a table.
But when I execute the insert, it says me that the column doesn't exist.
Here is the function :
CREATE OR REPLACE FUNCTION insert_id_function()
RETURNS trigger AS'
BEGIN
NEW.previewcontent = previewcontent || ''{"id":1}'';
RETURN NEW;
END;'
LANGUAGE plpgsql VOLATILE;
Here is the trigger :
CREATE TRIGGER insert_id_trigger
BEFORE INSERT
ON "Telnet"
FOR EACH ROW
EXECUTE PROCEDURE insert_id_function();
Here is the error :
`ERROR: column "previewcontent" does not exist LINE 1: SELECT previewcontent || '{"id":1}'`
Here is my table definition :

This is a column of the NEW record:
NEW.previewcontent = NEW.previewcontent || ''{"id":1}'';
If the type of previewcontent is jsonb use jsonb_build_object() to add the current value of id to the jsonb column:
CREATE OR REPLACE FUNCTION insert_id_function()
RETURNS trigger AS $$
BEGIN
NEW.previewcontent = NEW.previewcontent || jsonb_build_object('id', NEW.id);
RETURN NEW;
END;
$$ LANGUAGE plpgsql VOLATILE;

Related

Update columns for the first user inserted

I'm trying to create a trigger and a function to update some columns (roles and is_verified) for the first user created. Here is my function :
CREATE OR REPLACE FUNCTION public.first_user()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
begin
if(select count(*) from public.user = 1) then
update new set new.is_verified = true and new.roles = ["ROLE_USER", "ROLE_ADMIN"]
end if;
return new;
end;
$function$
;
and my trigger :
create trigger first_user
before insert
on
public.user for each row execute function first_user()
I'm working on Dbeaver and Dbeaver won't persist my function because of a syntax error near the "=". Any idea ?
Quite a few things are wrong in your trigger function. Here it is revised w/o changing your business logic.
However this will affect the second user, not the first. Probably you shall compare the count to 0. Then the condition shall be if not exists (select from public.user) then
CREATE OR REPLACE FUNCTION public.first_user()
RETURNS trigger LANGUAGE plpgsql AS
$function$
begin
if ((select count(*) from public.user) = 1) then
-- probably if not exists (select from public.user) then
new.is_verified := true;
new.roles := array['ROLE_USER', 'ROLE_ADMIN'];
end if;
return new;
end;
$function$;

PostgreSQL trigger not executing after update [duplicate]

Here is my trigger function
CREATE OR REPLACE FUNCTION test_table_insert()
RETURNS TRIGGER
AS $$
BEGIN
IF NEW.id IS NULL THEN
RAISE EXCEPTION 'id is null';
END IF;
UPDATE e_sub_agreement SET ro_id = NEW.id WHERE id = NEW.id;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER test_table_insert AFTER INSERT ON e_sub_agreement FOR EACH ROW EXECUTE PROCEDURE test_table_insert();
The problem is that it doesn't update table e_sub_agreement. I checked NEW value and everything is good. It returns with the new id. If I change where statement id = "some existing id in table", then it works. It changes ro_id to the new id. How is it possible? My guess is that data has not been inserted into table and trigger function can't find row with the given id. But it's not how trigger's after insert function works. What's the magic?
An AFTER trigger can not change anything. Running an additional UPDATE is also quite inefficient. Change this to a BEFORE trigger and assign the value you want:
CREATE OR REPLACE FUNCTION test_table_insert()
RETURNS TRIGGER
AS $$
BEGIN
IF NEW.id IS NULL THEN
RAISE EXCEPTION 'id is null';
END IF;
NEW.ro_id := NEW.id;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER test_table_insert
BEFORE INSERT ON e_sub_agreement
FOR EACH ROW EXECUTE PROCEDURE test_table_insert();
Note that the NOT NULL check is better done by defining the column as NOT NULL.

Execute a query for every row of a table inside a trigger function

I have made the following query which is working perfect by itself but when i call it inside trigger function i got problem.
select insert_new_grade('title0', return3_6(0), return3_6(1), return3_6(2), s.code)
FROM "student" as s
where find_st(s.grade)>=5;
insert_new_grade is a function that inserts a new row in a table every time it's being called.
Here is the trigger :
CREATE OR REPLACE FUNCTION insert_d()
RETURNS TRIGGER AS $$
BEGIN
select insert_new_grade('title0', return3_6(0), return3_6(1), return3_6(2), s.code)
FROM "student" as s
where find_st(s.grade)>=5;
return new;
END;
$$ LANGUAGE plpgsql;
and here is the insert function :
CREATE OR REPLACE FUNCTION insert_new_grade(title0 character(100), prof0 character(11), prof1 character(11))
RETURNS VOID AS $$
BEGIN
INSERT INTO "d_table"(thes0, title, grade, prof, secProf)
VALUES (null, title0, null, prof0, prof1);
END
$$
LANGUAGE 'plpgsql';
Is there a way to make the query work inside the trigger function ? If i use perform instead of select the insert function does not have result. I've read about cursors but I'm new in postgresql and I don't know how to do it. Any help ?
i modifited your trigger function:
check your trigger function in conlose pgAdmin, is visible raise info text
CREATE OR REPLACE FUNCTION insert_d()
RETURNS TRIGGER AS $$
declare
rec record;
BEGIN
for rec in (select * from student s where find_st(s.grade)>=5) loop
raise info 'LOOP code = %',rec.code;
PERFORM insert_new_grade('title0', return3_6(0), return3_6(1), return3_6(2), rec.code);
end loop;
return new;
END;
$$ LANGUAGE plpgsql;

How can alter the values of a composite type column inside trigger function before insert?

I have a table which has the following columns:
inspireId type : inspireid (composite type)
gid type : integer (primary key)
The inspireId column type is as following :
CREATE TYPE inspireId AS (
nameSpace text,
local_id integer
)
I want to fill local_id automatically with the value of gid when creating a new row in the table.
I tried the following :
CREATE OR REPLACE FUNCTION script.addLocalId() RETURNS TRIGGER AS
$$
BEGIN
NEW."inspireId".local_id := NEW.gid;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
But this is not working. The following error is thrown when creating the trigger function:
«new.inspireId.local_id» is not a known variable.
What is the right syntax for this?
You can not directly access to type element.
CREATE OR REPLACE FUNCTION script.addLocalId() RETURNS TRIGGER AS
$$
BEGIN
NEW."inspireId" = ((NEW.inspireId).nameSpace, NEW.gid)::inspireId;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION script.addLocalId() RETURNS TRIGGER AS
$$
BEGIN
SELECT (
'any value for nameSpace ',
NEW.gid
)::inspireId INTO NEW.inspireId;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Can we restrict a trigger on table to only perform inserts based on function that is being called by it? (PostgreSQL)

Is there any way in PostgreSQL where we can restrict the trigger to only do the insert's based on the function that is being called? Say, I created a trigger on fact_activity but whenever I perform any insert's the trigger should execute the function to perform inserts on the table defined in the function only.
--Here's my trigger that executes the function.
CREATE TRIGGER test_insert
BEFORE INSERT ON fact_activity
FOR EACH ROW
EXECUTE PROCEDURE insert_function();
--Insert function
CREATE OR REPLACE FUNCTION insert_function()
RETURNS trigger AS
$BODY$
DECLARE
l_part_date TEXT;
l_table_name TEXT;
BEGIN
l_part_date := to_char(TO_date(NEW.activity_date_key ::text,'YYYYMMDD'),'YYYY_MM');
l_table_name := TG_TABLE_NAME ||'_'|| l_part_date;
EXECUTE 'INSERT INTO ' || l_table_name || ' SELECT $1.*' USING NEW;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql;
Note: activity_date_key is of integer format (20150512). Hence the conversion.
The above script results in a record being inserted in both fact_activity & fact_activity_2015_05. But I only need to insert a record in fact_activity_2015_05.
--DDL for the tables:
CREATE TABLE fact_activity
(
gc_activity_key bigint NOT NULL DEFAULT nextval('fact_gc_activity_key_seq'::regclass),
user_key bigint,
user_category_key integer,
user_geographic_region_key integer,
activity_date_key integer
);
CREATE TABLE fact_activity_2015_05 ( )
INHERITS (fact_activity);
-- DML:
INSERT INTO fact_gc_activity(user_key, user_category_key, user_geographic_region_key,activity_date_key)
VALUES (6, 1, 1,20150515);
Thanks in advance.
The trigger should return NULL
CREATE OR REPLACE FUNCTION insert_function()
RETURNS trigger AS
$BODY$
DECLARE
l_part_date TEXT;
l_table_name TEXT;
BEGIN
l_part_date := to_char(TO_date(NEW.activity_date_key ::text,'YYYYMMDD'),'YYYY_MM');
l_table_name := TG_TABLE_NAME ||'_'|| l_part_date;
EXECUTE 'INSERT INTO ' || l_table_name || ' SELECT $1.*' USING NEW;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql;