referencing new Table as new_table not visible to the trigger function Postgresql - postgresql-11

I am new in Postgresql so this question may be dumb for you guys!
I am tring to use the referenced tables in a trigger function, but some how the function doesn't seem to have access on the referenced alias (new_table) :
CREATE FUNCTION Function_Name()
RETURNS TRIGGER AS
$$
BEGIN
SELECT tbl.some_field INTO new_table.other_field
from some_table as tbl;
return null;
END;
$$ LANGUAGE PLPGSQL;
I am having this error:
"new_table.other_field" is not a known variable
and here is the trigger code:
CREATE TRIGGER Trigger_Name
AFTER INSERT
ON Table_Name
REFERENCING NEW TABLE AS new_table
FOR EACH ROW
EXECUTE FUNCTION Function_Name();
The function code should be executed first and then the trigger's, so how could the function access the alias that is referenced later in the trigger defenition??
and how to access the referenced table aliases in the function?
Note: In my example I am tring to use the alias, so when I use NEW inplace of new_table the function is created successfully!

The problem was that i am tring to set data in the NEW table using the alias name, however to do that i should use the original name NEW and not the referenced alias new_table..
The referenced alias new_table could be used to only get data from, like in FROM CLAUSE, joins and WHERE CLAUSE where one doesn't change the data in the referenced table.
Update:
here is an example of what i did to test that:
create table test_table2(
id int primary key,
name varchar(255)
)
create table test_table(
id int primary key,
name varchar(255)
)
create or replace function F_test_table()
returns trigger as $$
begin
insert into test_table2(id, name)
select id, name from new_table;
return null;
end;
$$ LANGUAGE PLPGSQL;
drop trigger if exists tr_test_table ON test_table;
create trigger tr_test_table
AFTER INSERT
ON test_table
REFERENCING NEW TABLE AS new_table
for each row ------- row level trigger ---------
EXECUTE FUNCTION F_test_table();
insert into test_table
values(1, '11111')
select * from test_table2
notice that the trigger inserts the data into test_table2

Related

Redshift inserting `body` type into external table (incompatible type)

Here is a toy example:
I am creating an external table in Redshift:
CREATE EXTERNAL TABLE "external_schema"."test_table_01" (
"id" BIGINT,
"body" SUPER
)
STORED AS PARQUET
LOCATION 's3://some-bucket/test_table_01';
Now I attempt to insert into this table using a "select" statement:
insert into "external_schema"."test_table_01"
select 1::BIGINT as id, JSON_PARSE('{"a": 1}')::SUPER as body
Everything seems fine, but I get:
ERROR: Column 2 in the SELECT query has incompatible type with column "body" in the external table.
column body is clearly of SUPER type. I am also able to parse it, i.e. if I do:
with t as (select 1::BIGINT as id, JSON_PARSE('{"a": 1}')::SUPER as body)
select body.a from t
the above works, I get the result:
| a |
|---|
| 1 |
but not able to insert that data into the external table.

postgresql code for delete operation in table type

I have a code for deleting table type in MSSQL.Have to convert into PGSQL which is giving error.
Looking forward for a PGSQL code which deletes from a Table Type User defined:
below MSSQL CODE:
declare #Entity TRef_StructureTree readonly //input parameter from procedure
DELETE Tef_StructureTree
FROM Tef_StructureTree
inner join (select * from #Entity) as source
on Tef_StructureTree.ChildCodeBDR=source.ChildCodeBDR AND
Tef_StructureTree.ChildScheme=source.ChildScheme;
Below is definition of USer defined Table type:
CREATE TYPE [dbo].[Tef_StructureTree] AS TABLE(
[ChildCodeBDR] [numeric](10, 0) NOT NULL,
[ChildScheme] [nvarchar](100) NOT NULL,
)
below PGSQL CODE:
CREATE OR REPLACE FUNCTION UpdateStrucTree(v_entity Tef_StructureTree[])
as
begin
DELETE FROM v_entity
where v_entity."ChildCodeBDR" in(select "source"."ChildCodeBDR" from unnest(v_entity) as "source" )
and v_entity."ChildScheme" in (select "source"."ChildScheme" from unnest(v_entity) as "source" );
end;
ERROR: relation "v_entity" does not exist
Please Help by providing the equivalent!!
Your parameter is called v_entitydata not v_entity, so you either need to change your parameter name or the reference to it. You probably want to delete from the table Tef_StructureTree not from the passed array.
Your function's structure is also not valid for Postgres as the function body needs to be provided as a string, e.g. using dollar quoting.
You can simplify the condition, by only using a single sub-query as well.
So putting all that together, the function should look like this:
CREATE OR REPLACE FUNCTION UpdateStrucTree(v_entity "Tef_StructureTree"[])
as
$$
DELETE FROM "Tef_StructureTree"
where ("ChildCodeBDR", "ChildScheme") in (select "ChildCodeBDR", "ChildScheme"
from unnest(v_entity) )
$$
language sql;

Update column value from array element inside before insert trigger

i am trying to do a before insert trigger that updates one of the columns that will be inserted with a value taken from another column on the same record, however the catch is that that value is the first value of the said column after converting it to an array. when i include the function or the array i get a syntax error but the examples i have found for the proper syntax do not have the detail needed to make my code work. Here is my code:
Schema is as follows
create table events (
id int primary key,
performers varchar,
performer_id varchar
);
Function is:
create function events_set_performer() returns trigger
language plpgsql
as $$
declare
performer_ varchar := '0';
BEGIN
set NEW.performer_id = (string_to_array(NEW.performers,':'))[1];
return new;
END;
$$;

How to update redshift column: simple text replacement

I have a large target table with columns (id, value). I want to update value='old' to value='new'.
The simplest way would be to UPDATE target SET value='new' WHERE value='old';
However, this deletes and creates new rows and is not recommended, possibly. So I tried to do a merge column update:
# staging
CREATE TABLE stage (LIKE target INCLUDING DEFAULTS);
INSERT INTO stage (SELECT id, value FROM target WHERE value=`old`);
UPDATE stage SET value='new' WHERE value='old'; # ??? how do you update value?
# merge
begin transaction;
UPDATE target
SET value = stage.value FROM stage
WHERE target.id = stage.id and target.distkey = stage.distkey; # collocated join?
end transaction;
DROP TABLE stage;
This can't be the best way of creating the table stage: I have to do all these UPDATE delete/writes when I update this way. Is there a way to do it in the INSERT?
Is it necessary to force the collocated join when I use CREATE TABLE LIKE?
Are you updating all the rows in the table?
If yes you can use CTAS (create table as) which is recommended method
Assuming you table looks like this
table1
id, col1,col2, value
You can use the following SQL to create a new table
CREATE TABLE tmp_table AS
SELECT id, col1,col2, 'new_value'
FROM table1;
After you verify data in tmp_table
DROP TABLE table1;
ALTER TABLE tmp_table RENAME TO table1;
If you are not updating all the rows you can use a filter to do a CTAS and insert the rest of the rows to the new table, let me know if you need more info if this is the case
CREATE TABLE tmp_table AS
SELECT id, col1,col2, 'new_value'
FROM table1
WHERE value = 'old'
INSERT INTO tmp_table SELECT * from table1;
Next step would be DROP the tmp table and rename table1
Update: Based on your comment you can do the following, let me know if this solves your case.
This method basically creates a new table to replace your existing table.
I have used some of your code
CREATE TABLE stage (LIKE target INCLUDING DEFAULTS);
INSERT INTO stage SELECT id, 'new' FROM target WHERE value=`old`;
Above INSERT inserts rows to be updated with 'new', no need to run an UPDATE after this.
Bring unchanged rows
INSERT INTO stage SELECT id, value FROM target WHERE value!=`old`;
After this point you have target table which is your original table intact
stage table will have both sets of rows, updated rows with 'new' value and rows you did not want to change
To replace your target with stage
DROP TABLE target;
or to keep it further verification
ALTER TABLE target RENAME TO target_old;
ALTER TABLE stage RENAME TO target;
From a redshift developer:
This case doesn't require an upsert, or update+insert, and it is fine to just run the update:
UPDATE target SET value='new' WHERE value='old';
Another way would be to INSERT the rows you need and DELETE the other rows, but that's unnecessarily complicated.

Apex: How to find out the schema name?

I need to find my schema name because i want to delete triggers which i created.
For example the following:
CREATE OR REPLACE TRIGGER TRIGGER_ORDER
BEFORE INSERT ON HOUSE_ORDER
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
WHEN (NEW.ORDER_ID IS NULL)
BEGIN
SELECT SEQ_ORDER_ID.NEXTVAL
INTO :NEW.ORDER_ID FROM DUAL;
END;
/
When i now try to drop the trigger:
DROP TRIGGER TRIGGER_ORDER
I get the following error:
ORA-04080: trigger 'TRIGGER_ORDER' does not exist
I found out that i need to call something like
DROP TRIGGER SCHEMA_NAME.TRIGGER_ORDER
but i have no idea what my schema name is. so how can i find it?
You should use the ALL_TRIGGERS view. There's a column named Table Owner which indicates the schema.
select * from all_triggers
where table_name = 'YOUR_TABLE'