Is a primary key field NOT NULL by default in postgres? [duplicate] - postgresql

This question already has answers here:
Why can I create a table with PRIMARY KEY on a nullable column?
(5 answers)
Closed 1 year ago.
Is a primary key field NOT NULL by default in postgres, or does it need to be specified as such when creating the table?

Quote from the manual
Adding a primary key will automatically create a unique B-tree index on the column or group of columns listed in the primary key, and will force the column(s) to be marked NOT NULL.
(emphasis mine)

Related

PostgreSQL declarative partition - unique constraint on partitioned table must include all partitioning columns [duplicate]

This question already has an answer here:
ERROR: unique constraint on partitioned table must include all partitioning columns
(1 answer)
Closed last month.
I'm trying to create a partitioned table which refers to itself, creating a doubly-linked list.
CREATE TABLE test2 (
id serial NOT NULL,
category integer NOT NULL,
time timestamp(6) NOT NULL,
prev_event integer,
next_event integer
) PARTITION BY HASH (category);
Once I add primary key I get the following error.
alter table test2 add primary key (id);
ERROR: unique constraint on partitioned table must include all partitioning columns
DETAIL: PRIMARY KEY constraint on table "test2" lacks column "category" which is part of the partition key.
Why does the unique constrain require all partitioned columns to be included?
EDIT: Now I understand why this is needed: https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITIONING-DECLARATIVE-LIMITATIONS
Once I add PK with both columns it works.
alter table test2 add primary key (id, category);
But then adding the FK to itself doesn't work.
alter table test2 add foreign key (prev_event) references test2 (id) on update cascade on delete cascade;
ERROR: there is no unique constraint matching given keys for referenced table "test2"
Since PK is not just id but id-category I can't create FK pointing to id.
Is there any way to deal with this or am I missing something?
I would like to avoid using inheritance partitioning if possible.
EDIT2: It seems this is a known problem. https://www.reddit.com/r/PostgreSQL/comments/di5mbr/postgresql_12_foreign_keys_and_partitioned_tables/f3tsoop/
Seems that there is no straightforward solution. PostgreSQL simply doesn't support this as of v14. One solution is to use triggers to enforce 'foreign key' behavior. Other is to use multi-column foreign keys. Both are far from optimal.

Using primary keys in postgrSQL [duplicate]

This question already has answers here:
What is a PRIMARY KEY
(4 answers)
Closed 2 years ago.
I currently have a table:
userID | color | quantity
-------------------------
where userID is the primary key. My problem is when I try to insert to the DB (that already has one item from the same ID) I get the error: pq: duplicate key value violates unique constraint I am using Go with lib/pq package to insert.
I am unsure whether I have the wrong idea of what to use a PK for, or if I don't understand what kind of table I need to make
Primary key is a key that uniquely identifies each single row in the table and therefore needs to be unique. If you need more rows with same userID in your table then userID cannot be a primary key.
When you specify column (or group of columns) as a primary key PostgreSQL will put uniqueness constraint on it so it cannot happen that two rows in table have same contents of that column - that's why you see constraint violation error.
You can solve this problem by adding another ID column that will have unique value for each row (e.g. autoincremented sequence) and making it primary key instead of userID.
Here is a detailed tutorial on primary key in Postgres to give you a better understanding of primary key usage.

How to efficiently add an auto-incrementing primary key to an existing column in postgres? [duplicate]

This question already has answers here:
PostgreSQL, reconfigure existing table, changing primary key to type=serial
(1 answer)
How to convert primary key from integer to serial?
(1 answer)
Closed 3 years ago.
Problem
I can add an auto-incrementing primary key to a pre-existing column in an empty table in postgres, but I wonder if it can be done more efficiently.
What I've Done
Before the table gets populated, I need to alter a column to add an auto-incrementing primary key. Similar to the answer to this question, the following will work (assuming the table is named test and the column in question is named col1):
ALTER TABLE test ADD PRIMARY KEY (col1);
CREATE SEQUENCE seq OWNED BY test.col1;
ALTER TABLE test ALTER COLUMN col1 SET DEFAULT nextval('seq');
UPDATE test SET col1 = nextval('seq');
Four lines is far from the end of the world. However, as per that answer, this can be done in one line if we're adding a column rather than altering a pre-existing one:
ALTER TABLE test ADD COLUMN col1 SERIAL PRIMARY KEY;
Question
Is there a way to do that in one line, but for a pre-existing column? It seems like SERIAL is limited to when one adds a new column, but I figured it can't hurt to ask. My naive attempts included things like:
ALTER TABLE test ALTER COLUMN col1 SERIAL PRIMARY KEY;
ALTER TABLE test ADD SERIAL PRIMARY KEY (col1);
Thanks!
EDIT: This got marked as a duplicate right off the bat, though I read both of those questions coming into this. I feel like they both use the same methodology that I'm already using (unless I misunderstood what was at play), and my question is about seeing if there's a more efficient way to do it, especially since there is in new column creation.

How to assign serial as a primary key for the existing data? [duplicate]

This question already has answers here:
How to convert primary key from integer to serial?
(1 answer)
PostgreSQL - create an auto-increment column for non-primary key
(2 answers)
How can I add a 2nd serial integer key column to a table? (postgresql)
(1 answer)
Closed 4 years ago.
I have a table in the postgres for which I dint assign any primary key as the values are repeated, but now I want to add primary key for it by altering the table and adding serial column as a primary key . Will it allow me to do that, will it assign the serial numbers for the existing data after I alter the table? What would be the best practice to do that?
alter table t
add column i serial primary key;
https://www.postgresql.org/docs/current/static/sql-altertable.html

UNIQUE constraint where NULL is one valid value [duplicate]

This question already has answers here:
Create unique constraint with null columns
(5 answers)
Closed 7 years ago.
Inn PostgreSQL I want to have a multi-column UNIQUE constraint where one of the columns can be NULL exactly once.
What I've tried so far:
ALTER TABLE customexternalemail
ADD CONSTRAINT customexternalemail_sp_emaildomain_unique
UNIQUE(serviceproviderid, emailprefix, emaildomainid);
Where serviceproviderid and emaildomainid are BIGINT, and emailprefix is TEXT. emaildomainid is the only column with NULL allowed, and is the column I'm having trouble with.
Basically, I want to allow only one entry matching a combination of serviceproviderid, emailprefix, and emaildomainid, where emaildomainid could be a BIGINT value or NULL. Currently (with the above constraint), it will accept repeats if emaildomainid is NULL, but if emaildomainid is not NULL, it must be unique.
You can create two partial indexes. They are supported since version 7.2, which was released in February 2002.
This one will check that any combinaison of the three columns will be unique when emaildomainid isn't null:
CREATE UNIQUE INDEX customexternalemail_sp_emaildomain_unique_not_null
ON customexternalemail (serviceproviderid, emailprefix, emaildomainid)
WHERE emaildomainid IS NOT NULL;
This one will ensure that for any row which has a null value for emaildomainid, the combination (serviceproviderid, emailprefix) will be unique:
CREATE UNIQUE INDEX customexternalemail_sp_emaildomain_unique_null
ON customexternalemail (serviceproviderid, emailprefix)
WHERE emaildomainid IS NULL;