Setting constraint for two unique fields in PostgreSQL - postgresql

I'm new to postgres. I wonder, what is a PostgreSQL way to set a constraint for a couple of unique values (so that each pair would be unique). Should I create an INDEX for bar and baz fields?
CREATE UNIQUE INDEX foo ON table_name(bar, baz);
If not, what is a right way to do that? Thanks in advance.

If each field needs to be unique unto itself, then create unique indexes on each field. If they need to be unique in combination only, then create a single unique index across both fields.
Don't forget to set each field NOT NULL if it should be. NULLs are never unique, so something like this can happen:
create table test (a int, b int);
create unique index test_a_b_unq on test (a,b);
insert into test values (NULL,1);
insert into test values (NULL,1);
and get no error. Because the two NULLs are not unique.

You can do what you are already thinking of: create a unique constraint on both fields. This way, a unique index will be created behind the scenes, and you will get the behavior you need. Plus, that information can be picked up by information_schema to do some metadata inferring if necessary on the fact that both need to be unique. I would recommend this option. You can also use triggers for this, but a unique constraint is way better for this specific requirement.

Related

Postgres create table like exclude constraints but include indexes

I am trying to recreate a table's structure using following statement. However I would like to exclude constraints but include indexes from the original table.
CREATE TABLE users_audit (like users EXCLUDING CONSTRAINTS);
Above statement works as expected as it create a new table users_audit without constraints. However I am not sure if it is possible to copy indexes using INCLUDING INDEXES or even include everything except primary key constraint. Looking at the documentation it seems like I can only pass EXCLUDING | INCLUDING.
You can say
CREATE TABLE users_audit (like users EXCLUDING CONSTRAINTS INCLUDING INDEXES);
That will create all indexes, so it also will create the indexes that implement primary key and unique constraints. However, foreign key constraints won't be created.
There is no way to only create the indexes that do not belong to a constraint. For that, you could say INCLUDING INDEXES and afterwards drop all constraints.

Index in postgresql

Firstly, I have a table in database USERS with almost 30 Million records in it. I have different indices for each column. But some of the column have only 2 to 3 non null values while others are Null but still their index size is 847 MB a little less than the one index that contain unique value for each row.
Can anyone know why is it like this?
Secondly, in PostgreSQL we have a index for primary key index for each column by default what if we delete that index what will be the consequences?
What that index is really use for?
As i'm searching based on values in other columns only will it be safe to delete index for primary key?
NULL values are stored in indexes just like all other values, so the first part is not surprising.
You cannot delete the primary key index, what you could do is drop the primary key constraint. But then you cannot be certain that no duplicate rows get added to the table. If you think that is no problem, look at the many questions asking for help with exactly that problem.
Every table should have a primary key.
But it might be a good idea to get rid of some other indexes if you don't need them.
There is nothing called primary key index, seems to be you are talking about unique index.
First of all you need to understand the difference between primary key and index. You can have only one primary key in a table. Primary key would be your unique identifier of each column and does not allow nulls. Index is used to speed up your fetching process on particular column and you can have one null if it is unique index. Deleting unique index in your table will not impact any thing apart from performance. Its your way of design to have index or not

Postgres JSONB unique constraint

I have a table as following table.
create table person {
firstname varchar,
lastname varchar,
person_info jsonb,
..
}
I already have unique constraints on firstname + lastname. I recently identify there is always something different in person_info jsonb. I want to uniquely identify by person_info jsonb.
Should I add person_info as part of unique constraints firstname + lastname + person_info ? Is there any performance impact with such implementation ? I heard JSONB is not good for index when number of data increases.
I am thinking to use store person_info hashvalue in different field and combine this new hashvalue field as part of unique index.
I would appreciate if I get some help from expert on this.
This seems like a wrong idea.
A primary key should be immutable and uniquely identify a table row.
Names are not good for that, because
different people can have the same name
names can change
This is probably why you are tempted to add additional information to truly identify each individual row.
Unless you have some immutable attribute that uniquely identifies each person (such as the social security nubmer), you should generate an artificial primary key for the table:
ALTER TABLE person
ADD id bigint
GENERATED ALWAYS AS IDENTITY
PRIMARY KEY;
Indexing a jsonb is possible, but you will get problems with long values since index entries are limited in size, and you will get an error if you exceed the limit.
I recommend that any attribute that you might want to index is not stored in a jsonb, but as a regular table column.
JSONB indexing IMHO refers to the ability to index fields inside the binary JSON rather than the whole block. Be aware also that key ordering is not kept! So if you can obtain two different hashes for two json with the exact same data but different ordering. Instead, if you can find which json fields gives you uniqueness, than you can use directly those for indexing.
Try also to look at this page

ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found

This can be marked as duplicate but I am finding issue when I refereed
Create Unqiue case-insensitive constraint on two varchar fields
I have a table std_tbl having some duplicate records in one of the columns say Column_One.
I created a unique constraint on that column
ALTER TABLE std_tbl
ADD CONSTRAINT Unq_Column_One
UNIQUE (Column_One) ENABLE NOVALIDATE;
I used ENABLE NOVALIDATE as I want to keep existing duplicate records and validate future records for duplicates.
But here, the constaint does not look for case sensitive words, like if value of Column_One is 'abcd', it allows 'Abcd' and 'ABCD' to insert in the table.
I want this behaviour to be case insensitive so that it should not look for case while validating data. For this I came up with this solution.
CREATE UNIQUE INDEX Unq_Column_One_indx ON std_tbl (LOWER(Column_One));
But it is giving me the error:
ORA-01452: cannot CREATE UNIQUE INDEX; duplicate keys found
Please help me out...
This occurs when you try to execute a CREATE UNIQUE INDEX statement on one or more columns that contain duplicate values.
Two ways to resolve (that I know of):
Remove the UNIQUE keyword from your CREATE UNIQUE INDEX statement and rerun the command (i.e. if the values need not be unique).
If they must be unique, delete the extraneous records that are causing the duplicate values and rerun the CREATE UNIQUE INDEX statement.

Composite key with user-supplied string column, foreign keys

Let's say I have the following table
TABLE subgroups (
group_id t_group_id NOT NULL REFERENCES groups(group_id),
subgroup_name t_subgroup_name NOT NULL,
more attributes ...
)
subgroup_name is UNIQUE to a group(group_id).
A group can have many subgroups.
The subgroup_names are user-supplied. (I would like to avoid using a subgroup_id column. subgroup_name has meaning in the model and is more than just a label, I am providing a list of predetermined names but allow a user to add his owns for flexibility).
This table has 2 levels of referencing child tables containing subgroup attributes (with many-to-one relations);
I would like to have a PRIMARY KEY on (group_id, upper(trim(subgroup_name)));
From what I know, postgres doesn't allow to use PRIMARY KEY/UNIQUE on a function.
IIRC, the relational model also requires columns to be used as stored.
CREATE UNIQUE INDEX ON subgroups (group_id, upper(trim(subgroup_name))); doesn't solve my problem
as other tables in my model will have FOREIGN KEYs pointing to those two columns.
I see two options.
Option A)
Store a cleaned up subgroup name in subgroup_name
Add an extra column called subgroup_name_raw that would contained the uncleaned string
Option B)
Create both a UNIQUE INDEX and PRIMARY KEY on my key pair. (seems like a huge waste)
Any insights?
Note: I'm using Postgres 9.2
Actually you can do a UNIQUE constraint on the output of a function. You can't do it in the table definition though. What you need to do is create a unique index after. So something like:
CREATE UNIQUE INDEX subgroups_ukey2 ON subgroups(group_id, upper(trim(subgroup_name)));
PostgreSQL has a number of absolutely amazing indexing capabilities, and the ability to create unique (and partial unique) indexes on function output is quite underrated.