Alter table to add 'partition by range' in postgres - postgresql

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

Related

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.

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

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?

Many-to-one relationship using two unique keys

I have two tables which look like thiS:
uploads
________
id (primary key)
user_id
file_checksum
upload_information
---------
upload_info_id (primary key)
file_checksum
metadata1
metdata2
The "many to one" relationship I am trying to enforce is this:
Many uploads can have the same file checksum
However, the file checksum can only ever point to one upload_information record, thus making the unique constraint between file_checksum and upload_info_id mandatory in the upload_information table.
I am wondering how to alter these tables in Postgres in order to achieve this relationship.
CREATE TABLE uploads (
id SERIAL NOT NULL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
user_id VARCHAR NOT NULL,
file_checksum VARCHAR NOT NULL,
);
CREATE TABLE upload_information (
upload_info_id SERIAL NOT NULL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
file_checksum VARCHAR NOT NULL,
file_name VARCHAR NOT NULL,
source_file_url VARCHAR NOT NULL,
);
Add a unique index on file_checksum.
create unique index unique_checksum on upload_information(file_checksum)

with migration to fill slug with default value

In my Laravel 5.6/PostgreSQL 10.5 application
I have 2 tables :
CREATE TABLE public.rt_genres (
id serial NOT NULL,
published bool NULL DEFAULT false,
created_at timestamp NOT NULL DEFAULT now(),
updated_at timestamp NULL,
CONSTRAINT rt_genres_pkey PRIMARY KEY (id)
)...
CREATE TABLE public.rt_genre_translations (
id serial NOT NULL,
genre_id int4 NOT NULL,
"name" varchar(100) NOT NULL,
description text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
locale varchar(2) NOT NULL,
CONSTRAINT genre_translations_genre_id_locale_unique UNIQUE (genre_id, locale),
CONSTRAINT rt_genre_translations_pkey PRIMARY KEY (id),
CONSTRAINT genre_translations_genre_id_foreign FOREIGN KEY (genre_id) REFERENCES rt_genres(id) ON DELETE CASCADE
)
I need to add slug field in first rt_genres table
with migration rule:
$table->string('slug', 105)->unique();
and got error :
: Unique violation: 7 ERROR: could not create unique index "genres_slug_unique"
DETAIL: Key (slug)=(id) is duplicated.")
1)If there is a way to assign in migration some unique default value, like = id
->default('rt_genres.id')
?
2) That would be cool to assign to slug value from public.rt_genre_translations.name as I use
"cviebrock/eloquent-sluggable": "^4.5" plugin in my app ? Can I do it ?
Thank you!
You can only get the default value from a different column with a trigger (SO answer).
You can make the column nullable:
$table->string('slug', 105)->nullable()->unique();
Or you create the column, insert unique values and then create the index:
Schema::table('rt_genres', function($table) {
$table->string('slug', 105);
});
DB::table('rt_genres')->update(['slug' => DB::raw('"id"')]);
Schema::table('rt_genres', function($table) {
$table->unique('slug');
});

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.