PostgreSQL trigger for inserting an entry in table2 AFTER a row is inserted in table1 (using the values from newly inserted row in table1) - postgresql

I have displayed my database schema below.
CREATE TABLE table_group
(
group_id serial NOT NULL,
group_creator_id integer NOT NULL,
group_name character varying(20) NOT NULL,
active_status boolean NOT NULL,
PRIMARY KEY (group_id),
)
CREATE TABLE table_group_members
(
group_member_id serial NOT NULL,
group_id integer REFERENCES table_group (group_id) NOT NULL,
member_user_id integer REFERENCES table_group (group_creator_id) NOT NULL,
PRIMARY KEY (group_member_id)
)
I want to INSERT a new row in the table table_group_members as soon a new row is inserted in table table_group.
I want to pass the group_id and group_creator_id of the newly inserted row in the table table_group as parameters to INSERT query for the table table_group_members
How should I do it using the PostgreSQL TRIGGER?

Related

How to upsert into a table without setting an index?

Suppose the following setup:
create table chat_message (
id serial primary key,
message_id bigint unique not null, -- id from third party service
message_type varchar(255) unique not null
);
I can upsert into this table like this:
-- insert first record
insert into chat_message
values(1, 1234, 'start_message');
-- upsert
insert into chat_message (message_id, message_type)
values(1260, 'start_message')
on conflict (message_type)
do update set message_id = 1260;
This works fine, but I need to structure the table like this:
create table chat_message (
id serial primary key,
message_id bigint unique not null,
message_type varchar(255) not null -- this isn't necessarily unique
);
How can I accomplish this? Sure, message_id will always be unique, but there could be many messages with message_type = 'start_message'

Postgresql - delete on cascade not deleting from a child table

I have tables master_bill and master_bill_order_leg and order_leg.
MasterBill and OrderLeg have many to many relationship.
This is the quick documentation from IntelliJ for the DB tables.
Table master_bill:
create table master_bill
(
id bigint not null
primary key,
mb_no bigint not null,
created_by text not null,
updated_by text not null,
created_at timestamp with time zone default now() not null,
updated_at timestamp with time zone default now() not null
);
Table master_bill_order_leg:
create table master_bill_order_leg
(
mb_id bigint
references master_bill
on delete cascade,
order_leg_id bigint
references order_leg
on delete cascade,
constraint master_bill_order_mb_id_order_leg_id_key
unique (mb_id, order_leg_id)
);
Table order_leg:
create table order_leg
(
id bigserial
primary key,
created_by text not null,
updated_by text not null,
created_at timestamp with time zone default now() not null,
updated_at timestamp with time zone default now() not null,
constraint order_leg_unique_c
unique (flight_id, flight_date, departure_iata, arrival_iata)
);
I have set the foreign keys and they look like this:
Table master_bill_order_leg
master_bill_order_leg_mb_id_fkey (mb_id) -> master_bill(id)
master_bill_order_leg_order_leg_id_fkey (order_leg_id) -> order_leg(id)
I thought that if I delete a row from the parent master_bill table that all relevant rows from the child table master_bill_order_leg would be deleted too because of foreign keys that are set with on delete cascade. So, I have tried with deleting a row from master_bill table:
DELETE
FROM master_bill
WHERE id = :mbId
But, then I get an error:
org.postgresql.util.PSQLException: ERROR: update or delete on table
"master_bill" violates foreign key constraint
"master_bill_order_leg_mb_id_fkey" on table
"master_bill_order_leg" Detail: Key (id)=(1076) is
still referenced from table "master_bill_order_leg".
Why do I get this error, what am I doing wrong here?
If I run this query directly from the query console then a row is deleted from the table master_bill and a child table master_bill_order_leg.

Alter table to add 'partition by range' in postgres

I want to alter table with adding partition by range with archivedate.
CREATE TABLE transactions(
id UUID not null ,
txn_id UUID NOT NULL,
orderId UUID NOT NULL,
inserttstmp timestamp not NULL
archivedate timestamp NULL
)
usually, whenever i'm creating new table with partition with below script. But now want to do same for existing tables.
CREATE TABLE attachment(
id UUID not null,
txn_id UUID NOT NULL,
attachment_id UUID NOT NULL,
inserttstmp timestamp not NULL
archivedate timestamp NULL
)PARTITION BY RANGE (archivedate);
CREATE TABLE ins_txn_attachment_live PARTITION OF ins_txn_attachment DEFAULT;
ALTER TABLE ins_txn_attachment_live ADD CHECK (archivedate is null);
ALTER TABLE ins_txn_attachment_live ADD CONSTRAINT PK_INS_TXN_ATTACHMENT_EVENT_Live unique (id);
CREATE UNIQUE NONCLUSTERED INDEX PK_Ins_TXN_Attachment_ID_ArchiveData ON ins_txn_attachment (id,archivedate);
Thanks,
Jagadeesh

I want to insert rows into history tables from actual tables (parent and child) on insertion of row into actual tables using postgresql trigger

For Example:
Consider my original tables are:
CREATE TABLE employees(
id serial primary key,
first_name varchar(40) NOT NULL,
last_name varchar(40) NOT NULL
);
CREATE TABLE employees_detail
(
eid integer NOT NULL,
id integer,
first_name character varying(40),
last_name character varying(40),
CONSTRAINT employees_detail_pkey PRIMARY KEY (eid),
CONSTRAINT employees_detail_id_fkey FOREIGN KEY (id)
REFERENCES employees (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
The above tables have foreign key relation. So when I insert a row into both the tables, at the same time I want to insert them into history tables.
consider history tables are:
CREATE TABLE employee_audits (
id serial primary key,
employee_id int4 NOT NULL,
last_name varchar(40) NOT NULL,
changed_on timestamp(6) NOT NULL
)
CREATE TABLE employee_audits_detail
(
eid integer NOT NULL,
id integer,
last_name character varying(40),
changed_on timestamp(6) NOT NULL,
CONSTRAINT employee_audits_detail_pkey PRIMARY KEY (eid),
CONSTRAINT employee_audits_detail_fkey FOREIGN KEY (id)
REFERENCES employee_audits (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
I have created below trigger to insert into original parent table(employees) to history parent table(employee_audits). My trigger is as follows:
CREATE OR REPLACE FUNCTION log_last_name_changes()
RETURNS trigger AS
$BODY$
BEGIN
IF NEW.last_name <> OLD.last_name THEN
INSERT INTO employee_audits(employee_id,last_name,changed_on)
VALUES(OLD.id,OLD.last_name,now());
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql
CREATE TRIGGER last_name_changes
BEFORE UPDATE
ON employees
FOR EACH ROW
EXECUTE PROCEDURE log_last_name_changes();
Same way I want to insert original child table rows into history child table.

Postgres before insert trigger using sequence from another table

Using Postgres, what I would like to achieve is to be able to have many different instrument types, with corresponding [TYPE].instrument tables, which all have a unique ID in the table, but also reference a unique ID in the instrument.master table. I have the following:
create schema instrument
CREATE TABLE instrument.type (
id smallserial NOT NULL,
name text not null,
code text not null,
CONSTRAINT pk_instrument_type PRIMARY KEY (id)
);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_code UNIQUE(code);
ALTER TABLE instrument.type ADD CONSTRAINT unq_instrument_type_name UNIQUE(name);
insert into instrument.type (name, code) values ('futures', 'f');
CREATE TABLE instrument.master (
id serial NOT NULL,
type smallint not null references instrument.type (id),
timestamp timestamp with time zone not null,
CONSTRAINT pk_instrument_master PRIMARY KEY (id)
);
CREATE TABLE futures.definition (
id smallserial NOT NULL,
code text not null,
CONSTRAINT pk_futures_definition PRIMARY KEY (id)
);
ALTER TABLE futures.definition ADD CONSTRAINT unq_futures_definition_code UNIQUE(code);
insert into futures.definition (code) values ('ED');
CREATE TABLE futures.instrument (
id smallserial NOT NULL,
master serial not null references instrument.master (id),
definition smallint not null references futures.definition (id),
month smallint not null,
year smallint not null,
CONSTRAINT pk_futures_instrument PRIMARY KEY (id),
check (month >= 1),
check (month <= 12),
check (year >= 1900)
);
ALTER TABLE futures.instrument ADD CONSTRAINT unq_futures_instrument UNIQUE(definition, month, year);
CREATE OR REPLACE FUNCTION trigger_master_futures()
RETURNS trigger AS
$BODY$
BEGIN
insert into instrument.master (type, timestamp)
select id, current_timestamp from instrument.type where code = 'f';
NEW.master := currval('instrument.master_id_seq');
RETURN NEW;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
create trigger trg_futures_instrument before insert on futures.instrument
for each row
execute procedure trigger_master_futures();
I then test with:
insert into futures.instrument (definition, month, year)
select id, 3, 2015 from futures.definition where code = 'ED';
Everything works almost as I would like it to. The only issue is that somehow, instrument.master.id ends up being one more than futures.instrument.master. I am not sure what I need to do to achieve the behavior I want, which is that whenever an entry is inserted into futures.instrument, an entry should be inserted into instrument.master, and the id entry of the latter should be inserted into the master entry of the former. I actually think it should have failed since the foreign key relationship is violated somehow.
As it turns out, everything was correct. The issue was that in futures.instrument, the type of the master column is serial, and it should have been int.