NEED HELP - Create Trigger to update column - sql

Trying to create trigger function to update column in point layer to update column with ID from another point.
First layer - it's equipment installed on pole(second layer). Just want to fill information about pole when adding new equipment.
Tried this code: (I'm using similar for history backup)
--1.Create index in geometry column:
CREATE INDEX idx_sc_48_lom_ar5_geom ON mapinfo.public.sc_48_lom_ar5 USING GIST("SP_GEOMETRY");
--2. Function:
CREATE OR REPLACE FUNCTION mapinfo.public.sc_48_lom_ar5_tracker() RETURNS trigger AS $sc_48_lom_ar5_tracker$
BEGIN
-- INSERT
IF (TG_OP = 'INSERT') THEN
SELECT ST_Buffer("SP_GEOMETRY",5, 'quad_segs=8') FROM mapinfo.public.poles_lom_ar5;
UPDATE mapinfo.public.sc_48_lom_ar5
SET "Location_ID" = poles_lom_ar5."Location_ID"
FROM mapinfo.public.poles_lom_ar5
WHERE ST_Contains (mapinfo.public.sc_48_lom_ar5."SP_GEOMETRY", mapinfo.public.poles_lom_ar5."SP_GEOMETRY");
RETURN NEW;
-- UPDATE
ELSIF (TG_OP = 'UPDATE') THEN
SELECT ST_Buffer("SP_GEOMETRY",5, 'quad_segs=8') FROM mapinfo.public.poles_lom_ar5;
UPDATE mapinfo.public.sc_48_lom_ar5
SET "Location_ID" = poles_lom_ar5."Location_ID"
FROM mapinfo.public.poles_lom_ar5
WHERE ST_Contains (mapinfo.public.sc_48_lom_ar5."SP_GEOMETRY", mapinfo.public.poles_lom_ar5."SP_GEOMETRY");
RETURN NEW;
END IF;
END;
$sc_48_lom_ar5_tracker$ LANGUAGE plpgsql;
--3. Create trigger:
DROP TRIGGER IF EXISTS trg_sc_48_lom_ar5_tracker ON mapinfo.public.sc_48_lom_ar5;
CREATE TRIGGER trg_sc_48_lom_ar5_tracker AFTER INSERT OR UPDATE ON mapinfo.public.sc_48_lom_ar5
FOR EACH ROW EXECUTE PROCEDURE mapinfo.public.sc_48_lom_ar5_tracker();
SQL applying without errors, but when I'm trying to save edits I'm receiving error:
ODBC Error: ODBC RC=-1, ODBC SQLState=42601, DBMS RC=1,
DBMS Msg=ERROR: query has no destination for result data;
Error while executing the query. Operation cancelled.

Related

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.

Trigger postgreSQL

So. I tried made a trigger for updating quality medicament( i take quality from delivery.quality and put in medicaments.quality)
create or replace function addedmed()
returns trigger
language plpgsql
as
$$
begin
update medicaments set medicaments.quality = delivery.quality + medicaments.quality
where medicaments.id_med = delivery.id_med_del;
end;
$$;
and then - i try insert data to delivery
insert into delivery(id_del,id_provider,date_of_get,id_worker_del,id_med_del,quality)
values (default, 3 , current_timestamp ,1 ,6 ,10);
and then i have a exception -
ЗАПРОС: update medicaments set medicaments.quality = delivery.quality + medicaments.quality
where medicaments.id_med = delivery.id_med_del
КОНТЕКСТ: PL/pgSQL function addedmed() line 3 at SQL statement
so, pls help me, because i dont know how resolve it
This is not valid trigger function code. If you want to refer to the row being inserted in delivery, then use pseudo-table new, not delivery.
create or replace function addedmed()
returns trigger
language plpgsql
as $$
begin
update medicaments set quality = quality + new.quality where id_med = new.id_med_del;
return new;
end;
$$;
Note that the trigger returns the new record. You can then actually create the trigger as follows:
create trigger trg_addedmed
before insert on delivery
for each row
execute addedmed()
;
I defined a before insert trigger, you can change that to after insert if you prefer (in that case you can return null instead of new).

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 Update trigger

I have a table:
CREATE TABLE annotations
(
gid serial NOT NULL,
annotation character varying(250),
the_geom geometry,
"rotationAngle" character varying(3) DEFAULT 0,
CONSTRAINT annotations_pkey PRIMARY KEY (gid),
CONSTRAINT enforce_dims_the_geom CHECK (st_ndims(the_geom) = 2),
CONSTRAINT enforce_srid_the_geom CHECK (st_srid(the_geom) = 4326)
)
And trigger:
CREATE TRIGGER set_angle
AFTER INSERT OR UPDATE
ON annotations
FOR EACH ROW
EXECUTE PROCEDURE setangle();
And function:
CREATE OR REPLACE FUNCTION setAngle() RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
UPDATE annotations SET "rotationAngle" = degrees( ST_Azimuth( ST_StartPoint(NEW.the_geom), ST_EndPoint(NEW.the_geom) ) )-90 WHERE gid = NEW.gid;
RETURN NEW;
ELSIF TG_OP = 'UPDATE' THEN
UPDATE annotations SET "rotationAngle" = degrees( ST_Azimuth( ST_StartPoint(NEW.the_geom), ST_EndPoint(NEW.the_geom) ) )-90 WHERE gid = NEW.gid;
RETURN NEW;
END IF;
END;
$$ LANGUAGE plpgsql;
And when new row inserted in table or row edited i want to field rotationAngle setted with function result.
But when i inserting a new row in table function not work. I mean thath rotationAngle value not changed.
What can be wrong?
You are triggering an endless loop. Simplify the trigger function:
CREATE OR REPLACE FUNCTION set_angle()
RETURNS trigger
LANGUAGE plpgsql AS
$func$
BEGIN
NEW."rotationAngle" := degrees(
ST_Azimuth(
ST_StartPoint(NEW.the_geom)
, ST_EndPoint(NEW.the_geom)
)
) - 90;
RETURN NEW;
END
$func$;
Assign to NEW directly. No WHERE in this case.
You must double-quote illegal column names. Better not to use such names to begin with.
Recent related answer.
Code for insert & upgrade is the same. I folded into one code path.
Use a BEFORE trigger. This way you can edit columns of the triggering row directly before they are saved:
CREATE TRIGGER set_angle
BEFORE INSERT OR UPDATE ON annotations
FOR EACH ROW EXECUTE PROCEDURE set_angle();
However
If you are just trying to persist a functionally dependent value in the table (and there are no other considerations): Don't. Use a view or a generated column instead:
Store common query as column?
Then you don't need any of this.
There are multiple things wrong here.
1) When you insert a row 'A' the function setAngle() is called. But in the function you are calling another update within the function which will trigger the function again, and again, and so on...To fix this don't issue a update! Just update the NEW records value independently and return it.

trigger to update particular column in table A after update on table A

I am using postgresql and I want to update a column by summing up other column in the table.
EX: table name is A. When col1 or col2 or any column value in table A
is updated then the value of col6 should also be updated as
col6=(col1+col2+col3)
for this i have written a update trigger as below.
CREATE FUNCTION update_total2() RETURNS TRIGGER AS $_$
BEGIN
UPDATE hr_contract SET "x_TOTAL"=(NEW.x_othr_allow+NEW.x_med_allw+NEW."x_LTA"+NEW.wage+NEW.supplementary_allowance) WHERE id = OLD.id;
RETURN OLD;
END $_$ LANGUAGE 'plpgsql';
CREATE TRIGGER hr_contract_after_update
AFTER update ON hr_contract
FOR EACH ROW
EXECUTE PROCEDURE update_total2();
It is giving error as below..
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."res_users" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR SHARE OF x"
SQL statement "UPDATE hr_contract SET "x_TOTAL"=(NEW.x_othr_allow+OLD.x_med_allw+OLD."x_LTA"+OLD.wage+OLD.supplementary_allowance) WHERE id = OLD.id"
PL/pgSQL function update_total_result() line 3 at SQL statement
SQL statement "UPDATE hr_contract SET "x_TOTAL"=(NEW.x_othr_allow+OLD.x_med_allw+OLD."x_LTA"+OLD.wage+OLD.supplementary_allowance) WHERE id = OLD.id"
Any help is really very useful...
Try to check if any thing has changed on that row, and set the value of field x_TOTAL if any:
CREATE FUNCTION update_total2() RETURNS TRIGGER AS $_$
BEGIN
--Check if any of columns has been updated:
if tg_op='UPDATE' and old <> new then
NEW."x_TOTAL"= NEW.x_othr_allow+NEW.x_med_allw+NEW."x_LTA"+NEW.wage+NEW.supplementary_allowance);
end if;
RETURN NEW;
END $_$ LANGUAGE 'plpgsql';
--Associate triger to table on BEFORE update events
CREATE TRIGGER hr_contract_after_update
before update ON hr_contract
FOR EACH ROW
EXECUTE PROCEDURE update_total2();
Trigger documentation
I'm not familiar with postgresql syntax but the problem is that you are doing a recursive update. Your function update_total2 must not use UPDATE to the same table being updated on the trigger.
Please check documentation for details, all you have to do in the trigger itself is something like:
FOR EACH ROW
NEW.x_TOTAL = NEW.x_othr_allow + NEW.x_med_allw + NEW."x_LTA" + NEW.wage + NEW.supplementary_allowance