Cannot create primary key using already created index - postgresql

I have a table ideas with columns idea_id, element_id and element_value.
Initially, I had created a composite primary key(ideas_pkey) using all three columns but I started facing size limit issues with the index associated with the primary key as the element_value column had a huge value.
Hence, I created another unique index hashing the column with possible large values
CREATE UNIQUE INDEX ideas_pindex ON public.ideas USING btree (idea_id, element_id, md5(element_value))
Now I deleted the initial primary key ideas_pkey and wanted to recreate it using this newly created index like so
alter table ideas add constraint ideas_pkey PRIMARY KEY ("idea_id", "element_id", "element_value") USING INDEX ideas_pindex;
But this fails with the following error
ERROR: syntax error at or near "ideas_pindex"
LINE 2: ...a_id", "element_id", "element_value") USING INDEX ideas_...
^
SQL state: 42601
Character: 209
What am I doing wrong?

A primary key index can't be a functional index. You can instead just have a unique index on your table, or create another column storing the md5() of your larger column and use it in the PK.
That being said, there is also another error in your query: If you want to specify an index name, you can't specify the PK columns (they are derived from the underlying index). And if you want to specify the pk columns, you can't specify the index name/definition, as it will be automatically created. See the doc

Related

PostgreSQL Unique constraint and compound index

I have a table with a unique constraint on two fields, I also use this as an index for faster performance. I want to query a third field as part of this index but I don't want the third field to be part of the unique constraint. i.e. I don't want a new composite index just for the third field as it's quite large.
Is there a way to do this in Postgres? I presently create the unique constraint and get the index created for free, can I specify the three-field composite index and tell the unique constraint to use this index, and Postgres will figure out it can use this index as a UC?
You can use the INCLUDE option:
create unique index on the_table (column_1, column_2)
include (column_3);

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

Doesn't Postgres reuse unique indexes for unique key constraint?

Having experience with Oracle I assumed that each unique constraint would reuse unique index.
I created schema population script that creates named unique index and then same unique constraint. In that way I hoped to set index name explicitly rather than relay on Postgres default naming schema.
As experiment was shown I got two indexes with same definition in a result:
CREATE UNIQUE INDEX agent_ux ON agent (branch_id, initials);
ALTER TABLE agent ADD CONSTRAINT agent_uk UNIQUE (branch_id, initials);
select indexname from pg_indexes where tablename = 'agent';
agent_ux
agent_uk
Doesn't Postgres reuse unique indexes for unique key constraint?
NOTE I can't drop index, corresponding to unique constraint (error says about related constraint), but index is automatically deleted if I delete constraint.
In postgres, creating a UNIQUE constraint automatically creates an index. You can also create the constraint by promoting an existing index, using the ALTER TABLE ttt add constraint ccc USING xxx syntax: Documentation
ALTER TABLE agent
ADD CONSTRAINT agent_uk UNIQUE USING agent_ux;
[untested]

Dropping Unique Constraint - PostgreSQL

TL;DR
I am seeking clarity on this: does a FOREIGN KEY require a UNIQUE CONSTRAINT on the other side, specifically, in Postgres and, generally, in relational database systems?
Perhaps, I can test this, but I'll ask, if the UNIQUE CONSTRAINT is required by the FOREIGN KEY what would happen if I don't create it? Will the Database create one or will it throw an error?
How I got there
I had earlier on created a table with a column username on which I imposed a unique constraint. I then created another table with a column bearer_name having a FOREIGN KEY referencing the previous table's column username; the one which had a UNIQUE CONSTRAINT.
Now, I want to drop the UNIQUE CONSTRAINT on the username column from the database because I have later on created a UNIQUE INDEX on the same column and intuitively I feel that they serve the same purpose, or don't they? But the database is complaining that the UNIQUE INDEX has some dependent objects and so it can't be dropped unless I provide CASCADE as an option in order to drop even the dependent object. It's identifying the FOREIGN KEY on bearer_name column in the second table as the dependent object.
And is it possible for the FOREIGN KEY to be a point to the UNIQUE INDEX instead of the UNIQUE CONSTRAINT?
I am seeking clarity on this: does a FOREIGN KEY require a UNIQUE CONSTRAINT on the other side
No it does not require only UNIQUE CONSTRAINT. It could be PRIMARY KEY or UNIQUE INDEX.
Perhaps, I can test this, but I'll ask, if the UNIQUE CONSTRAINT is required by the FOREIGN KEY what would happen if I don't create it? Will the Database create one or will it throw an error?
CREATE TABLE tab_a(a_id INT, b_id INT);
CREATE TABLE tab_b(b_id INT);
ALTER TABLE tab_a ADD CONSTRAINT fk_tab_a_tab_b FOREIGN KEY (b_id)
REFERENCES tab_b(b_id);
ERROR: there is no unique constraint matching given keys
for referenced table "tab_b"
DBFiddle Demo
And is it possible for the FOREIGN KEY to be a point to the UNIQUE INDEX instead of the UNIQUE CONSTRAINT?
Yes, it is possible.
CREATE UNIQUE INDEX tab_b_i ON tab_b(b_id);
DBFiddle Demo2

Can I create an index on User-defined Table variables?

Just wanted to check, if we will be able to create indexes on User-defined Table variables. I know that we can create PK on an UDT. Does it imply that PK creates an (clustered) index internally? If an index is possible on a column on UDT, where does the indexed data get stored?
To define an index on a table variable use a primary key or unique constraint. You can nominate one as clustered.
If you need an index on a non-unique field, simply add the unique key to the end of the index column list, to make it unique.
If the table variable has not got a unique field, add a dummy unique field using an identity column.
Something like this:
declare #t table (
dummy identity primary key nonclustered,
val1 nvarchar(50),
val2 nvarchar(50),
unique clustered (val1, dummy)
)
Now you have a table variable with a clustered index on non-unique field val1.
With table variables, you can define primary key and unique constraints, but you are unable to define
any clustering behaviour. The indexes for these are stored alongside the actual data in the table variable - hopefully in memory within tempdb, but if necessary, spilled to disk, if memory pressure is high.
You're unable to define arbitrary indexes on such tables.
You can however define whatever indexes you want on temp tables.