Question for SAP DBTech JDBC when trigger is execute - sapui5

I would like to ask what is this error and how do I fix for it?
SAP DBTech JDBC: [7]: feature not supported: trigger execution with transition variable is not supported with piecewise lob writing.
Situation:
Read from a file that more than 100kb. Then insert into SAP HANA database.
The column to be inserted is BLOB type.
This table have a trigger which will insert the same information into another table (For tracking purpose).
If without this trigger, it able to insert data without any error.
I cannot give the actual code due to confidential. So I create a sample below.
I'm create a hdbtrigger file and compile it using SAP HANA Database Module in SAP Web IDE to create the table, trigger, etc.
TRIGGER "M_IMG_T_T"
AFTER INSERT OR UPDATE OR DELETE
ON "M_IMG_T"
REFERENCING NEW ROW new_row, OLD ROW old_row
FOR EACH ROW
BEGIN
DECLARE upd_kbn VARCHAR(1) := 'U';
IF :new_row."ID_PK" IS NULL THEN
upd_kbn = 'D';
ELSEIF :old_row."ID_PK" IS NULL THEN
upd_kbn = 'I';
END IF;
IF :upd_kbn = 'I' OR :upd_kbn = 'U' THEN
INSERT INTO "M_IMG_T_H" VALUES(
:new_row."ID_PK",
:new_row."I_IMG_FILE_DATA"
);
ELSE
INSERT INTO "M_IMG_T_H" VALUES(
:new_row."ID_PK",
:new_row."I_IMG_FILE_DATA"
);
END IF;
END
When I export catalog of the table, I will get this. (I just copy insert part)
CREATE TRIGGER "M_IMG_T_T_I" AFTER INSERT ON "M_IMG_T" REFERENCING NEW ROW NEW_ROW FOR EACH ROW
BEGIN
DECLARE UPD_CLS VARCHAR(2) := 'I';
INSERT INTO "M_IMG_T_H" (
"I_ID",
"I_IMG_FILE_DATA"
) VALUES(
:NEW_ROW."I_ID",
:NEW_ROW."I_IMG_FILE_DATA"
);
END

Related

Postgres dynamic insert in trigger function

I am trying to create a trigger function that insert a new record to the audit tables dynamically.
CREATE OR REPLACE FUNCTION schema.table()
RETURNS trigger
LANGUAGE 'plpgsql'
COST 100
VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
_tablename text;
BEGIN
_tablename := 'user_audit';
EXECUTE 'INSERT INTO audit.' || quote_ident(_tablename) || ' VALUES ($1.*)' USING OLD;
RETURN NEW;
END;
$BODY$;
Trigger function above works fine as it take everything in OLD and inserts it into the audit table as expected. However I have a tstzrange range column in my tables called timestampzt_range and what I need to do is set the value for it in audit table using LOWER(OLD.timestampzt_range), LOWER(NEW.timestampzt_range). How can I achieve this dynamically without using insert statement like below as I would like to use this trigger function on multiple tables.
INSERT INTO audit.user_audit
(
column_1,
column_2,
timestampzt_range
)
VALUES
(
OLD.column_1,
OLD.column_2,
tstzrange(LOWER(OLD.timestampzt_range), LOWER(NEW.timestampzt_range))
);
I only need to use this on update and table name will be passed as a parameter to the trigger function if I can achieve dynamic statement. Only the audit columns are consistent across the entire database so it is important for me create insert using OLD or somehow dynamically extract everything from it but the timestampzt_range and then use tstzrange(LOWER(OLD.timestampzt_range), LOWER(NEW.timestampzt_range)) as value for the range column.
First comment : you can use the NEW and OLD key words only in an UPDATE trigger. In an INSERT trigger, OLD doesn't exist. In a DELETE trigger, NEW doesn't exist. See the manual.
Then you can replace in your trigger function
'INSERT INTO audit.' || quote_ident(_tablename) || ' VALUES ($1.*)' USING OLD
by
'INSERT INTO audit.' || quote_ident(_tablename) || ' VALUES (OLD.column_1, OLD.column_2, tstzrange(LOWER(OLD.timestampzt_range), LOWER(NEW.timestampzt_range)))'
so that to achieve your expected result.
Last but not least, your dynamic statement EXECUTE 'INSERT INTO audit.' ... is useless because _tablename is a static parameter declared inside the function.

How to DELETE/INSERT rows in the same table using a UPDATE Trigger?

I want to create a trigger function, which copies certain columns of an recent updated row and deletes the old data. After that I want to insert the copied columns in exact the same table in the same row (overwrite). I need the data to be INSERTED because this function will be embedded in an existing program, with predefined Triggers.
That's what I have so far:
CREATE OR REPLACE FUNCTION update_table()
RETURNS TRIGGER AS
$func$
BEGIN
WITH tmp AS (DELETE FROM table
WHERE table.id = NEW.id
RETURNING id, geom )
INSERT INTO table (id, geom) SELECT * FROM tmp;
END;
$func$ language plpgsql;
CREATE TRIGGER T_update
AFTER UPDATE OF geom ON table
EXECUTE PROCEDURE update_table();
But I get the Error message:
ERROR: cannot perform DELETE RETURNING on relation "table"
HINT: You need an unconditional ON DELETE DO INSTEAD rule with a RETURNING clause.
Why I should use a rule here?
I'm using PostgreSQL 9.6
UPDATE:
A little bit of clarification. When I have two columns in my table (id, geom), after I updated geom I want to make a copy of this (new)row and insert it into the same table, while overwriting the updated row. (I'm not interested in any value before the update) I know that this is odd but I need this row to be inserted again because the program i embed this function in, listens to a INSERT statement and cannot be changed by me.
Right after you update a row, its old values will no longer be available. So, if you simply want to preserve the old row in case of an update you need to create a BEFORE UPDATE trigger, so that you can still access the OLD values and create a new row, e.g.
CREATE TABLE t (id int, geom geometry(point,4326));
CREATE OR REPLACE FUNCTION update_table() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO t (id, geom) VALUES (OLD.id,OLD.geom);
RETURN NEW;
END; $$ LANGUAGE plpgsql;
CREATE TRIGGER t_update
BEFORE UPDATE OF geom ON t FOR EACH ROW EXECUTE PROCEDURE update_table();
INSERT INTO t VALUES (1,'SRID=4326;POINT(1 1)');
If you update the record 1 ..
UPDATE t SET geom = 'SRID=4326;POINT(2 2)', id = 2 WHERE id = 1;
UPDATE t SET geom = 'SRID=4326;POINT(3 3)', id = 3 WHERE id = 2;
.. you get a new record in the same table as you wished
SELECT id, ST_AsText(geom) FROM t;
id | st_astext
----+------------
1 | POINT(1 1)
2 | POINT(2 2)
3 | POINT(3 3)
Demo: db<>fiddle
Unrelated note: consider upgrading your PostgreSQL version! 9.6 will reach EOL in November, 2021.
First thanks to #JimJones for the answer. I´d like to post his answer modified for this purpose. This code "overwrites" the updated row by inserting a copy of itself and then deleting the old duplicate. That way I can Trigger on INSERT.
CREATE TABLE t (Unique_id SERIAL,id int, geom geometry(point,4326));
CREATE OR REPLACE FUNCTION update_table() RETURNS TRIGGER AS $$
BEGIN
INSERT INTO t (id, geom) VALUES (NEW.id,NEW.geom);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER t_update
BEFORE UPDATE OF geom ON t FOR EACH ROW EXECUTE PROCEDURE update_table();
CREATE OR REPLACE FUNCTION delete_table() RETURNS TRIGGER AS $$
BEGIN
DELETE FROM t a
USING t b
WHERE a.Unique_id < b.Unique_id
AND a.geom = b.geom;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER t_delete
AFTER UPDATE OF geom ON t FOR EACH ROW EXECUTE PROCEDURE delete_table();
INSERT INTO t VALUES (1,1,'SRID=4326;POINT(1 1)');
UPDATE t SET geom = 'SRID=4326;POINT(2 2)' WHERE id = 1;

Using rules in postgresql to insert several rows

I need to insert several rows using a rule.
My problem is:
I draw a poligon and save on a table z0_poligono_corte, then I use a rule to get the intersection between the polygon in z0_poligono_corte and polygons in other table, but the result is not inserted in the table I created to save the results. Also there are no errors in the postgres log.
CREATE RULE cortar_anp AS ON INSERT TO z0_poligono_corte
DO also insert into z0_a_n_p_13 (id_poligono, folio, obs, anp, geometria) select pol.id, pol.folio, pol.obs, capa.anp, ST_Multi(ST_Intersection(capa.geom, pol.geometria))
from a_n_p_13 capa, z0_poligono_corte pol
where pol.id=NEW.id
and capa.geom && pol.geometria
and ST_IsEmpty(ST_Intersection(capa.geom, pol.geometria)) != TRUE;
I don't know if my rule is correct. If I run the insert into sentence using for example pol.id=1 then the result saves correctly.
image
I have not 10 reputation to put the image :(
Here the image
Thanks.
Here is how solved my problem with a trigger.
First i created a table
CREATE TABLE public.z0_poligono_corte (
id serial,
nombre character varying(255),
giro text,
geometria geometry(MultiPolygon,32614),
CONSTRAINT z0_poligono_corte_pkey PRIMARY KEY (id) )
After that I created a trigger function that makes the slice
CREATE OR REPLACE FUNCTION public.cortes_interseccion_amias()
RETURNS trigger AS
$BODY$
declare var_sql text;
begin
var_sql := 'insert into z0_amias08 (id_poligono, nombre, giro, tipo, geometria)
select pol.id, pol.nombre, pol.giro, capa.tipo, ST_Intersection(capa.geom, pol.geometria)
from amias08 capa, z0_poligono_corte pol
where pol.id=$1
and capa.geom && pol.geometria
and ST_IsEmpty(ST_Intersection(capa.geom, pol.geometria)) != TRUE';
execute var_sql using NEW.id;
return NEW;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Then the trigger.
CREATE TRIGGER interseccion_amias
AFTER INSERT
ON public.z0_poligono_corte
FOR EACH ROW
EXECUTE PROCEDURE public.cortes_interseccion_amias();
So when I insert a polygon on that table, the trigger function will cut on the table with data, then insert on the new table

GreenPlum - Table With Trigger - Insert Failed

This is my first time using triggers in green plum environment. I think I have most of it setup but I am facing some issues when I insert data. Here is my trigger
CREATE TRIGGER insert_trigger
BEFORE INSERT ON leads.abhi_temp
FOR EACH ROW EXECUTE PROCEDURE leads.my_trigger();
Here is the definition of the trigger
CREATE OR REPLACE FUNCTION leads.my_trigger()
RETURNS TRIGGER AS $$
BEGIN
IF ( NEW.date >= DATE '2003-01-01' AND
NEW.date < DATE '2003-12-31' ) THEN
INSERT INTO leads.abhi_temp_y2003 VALUES (NEW.*);
ELSIF ( NEW.date >= DATE '2004-01-01' AND
NEW.date < DATE '2004-12-31' ) THEN
INSERT INTO leads.abhi_temp_y2004 VALUES (NEW.*);
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
Now to insert data into my table I use
insert into leads.myData (select column1, column2 from leads.someOtherDara where column1 = '1');
But this gives me an error
ERROR: function cannot execute on segment because it issues a non-SELECT statement (functions.c:133)
I think the error is because I am using nested queries to insert data. Not sure how to fix this. Any recommendation. Thanks in advance for your help
I am aware, There is very limited support for triggers in Greenplum, It does not support DML operations.
May i know how do you achieve this, i mean how the rules can be applied as u said in your previous comments

db2 create procedure using razor

I am using RazorSQL tool to work with DB2. I try to create procedure which contains if table not exist statement.
the problem I am having is that if table doesn't exist it procedure has to execute create table statements.
trying co create a procedure returns error (syntax error), like it can not execute more then only create table statement.
example:
CREATE PROCEDURE KLEMENTEST.create_table
()
LANGUAGE SQL
MODIFIES SQL DATA
--READS SQL DATA
--CONTAINS SQL
begin atomic
if (not exists(select 'A' from syscat.tables where tabschema = 'KLEMENTEST' and tabname='bendeldoba')) then
create table klementest.bendeldoba (
bdd_id_bdd INTEGER not null,
bdd_naziv VARCHAR(128) not null,
bdd_mesecev INTEGER not null default 0,
bdd_prispevki INTEGER,
bdd_procent numeric,
bdd_racuni INTEGER,
bdd_datvpisa DATE not null,
bdd_vpisal_uporabnik INTEGER not null default 0
);
alter table klementest.bendeldoba add constraint P_Key_1 primary key (bdd_id_bdd);
end if;
end
alter table is causing the problems. If I comment it it works, also trying co execute smth like
CREATE PROCEDURE KLEMENTEST.create_table
()
LANGUAGE SQL
MODIFIES SQL DATA
--READS SQL DATA
--CONTAINS SQL
begin atomic
if (not exists(select 'A' from syscat.tables where tabschema = 'KLEMENTEST' and tabname='bendeldoba')) then
crete view def_schema.view1 as select * from sometable;
crete view def_schema.view2 as select * from someothertable;
end if;
end
it works
where is the "syntax error" problem with my first create procedure query??
thank you
In DB2, SQL stored procedures are bound statically in the database. This means that any static SQL statements (i.e. ones that you don't execute using PREPARE/EXECUTE or EXECUTE IMMEDIATE) will be checked and compiled when you create the stored procedure.
Therefore, the error occurs because when DB2 checks the ALTER TABLE statement to validity, the KLEMENTEST.BENDELDOBA does not yet exist.
The best way to resolve this is to make the ALTER TABLE statement a dynamic statement:
declare vSQL varchar(1024);
-- portion of procedure that creates the table...
set vSQL = 'alter table ...';
execute immediate vSQL;
I had to add some additional "setters", to declare where atomic procedure starts and ends
The code looks like this now
CREATE PROCEDURE KLEMENTEST.create_table
()
LANGUAGE SQL
ap: begin atomic
declare vsql varchar(1024) ;
set vSQL = 'alter table KLEMENTEST.avtvrsteplacilapod add constraint P_Key_1 primary key (avp_id_avp)';
if (not exists(select 'A' from syscat.tables where tabschema = 'KLEMENTEST' and tabname='AVTVRSTEPLACILAPOD')) then
create table KLEMENTEST.avtvrsteplacilapod (
avp_id_avp INTEGER not null,
avp_vrsteplacila INTEGER not null,
avp_naziv VARCHAR(64) not null,
avp_skupinevrpl INTEGER not null ,
avp_avtvrplmestovprog INTEGER ,
avp_postrm SMALLINT not null,
avp_upostzap SMALLINT not null
);
execute immediate vsql;
end if ;
end ap