PostgreSQL NOT NULL foreign key and default value with sequence - postgresql

I'm analyzing a following PostgreSQL schema:
CREATE SEQUENCE ref_email_type_ref_email_type_id_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;
CREATE TABLE ref_email_type
(
ref_email_type_id integer NOT NULL DEFAULT nextval('ref_email_type_ref_email_type_id_seq'::regclass),
description character varying(50) NOT NULL,
CONSTRAINT ref_email_type_pkey PRIMARY KEY (ref_email_type_id)
)
CREATE TABLE email
(
email_id integer NOT NULL DEFAULT nextval('email_email_id_seq'::regclass),
ref_email_type_id integer NOT NULL DEFAULT nextval('email_ref_email_type_id_seq'::regclass),
email_address character varying(100),
CONSTRAINT email_pkey PRIMARY KEY (email_id),
CONSTRAINT email_ref_email_type_id_fkey FOREIGN KEY (ref_email_type_id)
REFERENCES ref_email_type (ref_email_type_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
Does it make any sense to have email.ref_email_type_id declared with DEFAULT nextval('email_ref_email_type_id_seq'::regclass) in case of NOT NULL and existing constraint:
CONSTRAINT email_ref_email_type_id_fkey FOREIGN KEY (ref_email_type_id)
REFERENCES ref_email_type (ref_email_type_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION

No, that doesn't make any sense at all.
It won't do any harm either, since the default value will probably never be used.

Related

DB2 referential constraint cannot created

I can not add a referential constraint, both tables has the two columns id and version as primary key. I will only check the integrity that the row is existing without checking version.
CREATE TABLE TABLEE
(ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
PRIMARY KEY (ID , VERSION);
CREATE TABLE CHAIR
(ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
ID_TABLEE INTEGER,
PRIMARY KEY (ID , VERSION);
ALTER Chair
ADD constraint MYC FOREIGN KEY (ID)
REFERENCES TABLEE (ID)
ON DELETE RESTRICT
Got this error
[Code: -573, SQL State: 42890] A column list specified in the references clause of constraint "MYC " does not identify a unique constraint of the parent table or nickname "TABLEE".. SQLCODE=-573, SQLSTATE=42890, DRIVER=4.28.11
The problem here is that Tablee its primary key consists of two columns id and version. But the integrity check should only be made on the referenced id, not version.
To establish a foreign key on a table the referenced column needs to:
Be a primary key on the other table.
...or at least act as one.
Since you already have a primary key on the referenced table, you can use the second approach and add a UNIQUE and NOT NULL constraints on ID.
For example:
CREATE TABLE TABLEE (
ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
PRIMARY KEY (ID , VERSION),
constraint uq1 unique (id) -- added UNIQUE constraint on ID
);
CREATE TABLE CHAIR (
ID INTEGER NOT NULL,
VERSION INTEGER NOT NULL,
ID_TABLEE INTEGER,
PRIMARY KEY (ID , VERSION)
);
ALTER table Chair
ADD constraint MYC FOREIGN KEY (ID)
REFERENCES TABLEE (ID)
ON DELETE RESTRICT;
See running example at db<>fiddle.
Note: If you want ID to have repeated values over the table, then ID is not a key, and cannot be referenced as one.

Postgres violates not null constraint, even when there isn't one

Hey I have a Postgres database that has a Schema with
CREATE TABLE Mentor (
mentor_ID serial unique,
person_ID serial not null unique,
career_history varchar(255) not null,
preferred_communication varchar(50) not null,
mentoring_preference varchar(50) not null,
linked_in varchar(100) not null,
capacity int not null,
feedback_rating int,
feeback_comment varchar(255),
PRIMARY KEY (mentor_ID),
CONSTRAINT fk_person FOREIGN KEY (person_ID) REFERENCES Person(person_ID)
);
CREATE TABLE Mentee(
mentee_ID integer not null unique,
mentor_ID serial references Mentor(mentor_ID),
person_ID serial not null unique,
study_year int,
motivation varchar(50),
interests varchar(255),
random_match boolean default false,
PRIMARY KEY (mentee_ID),
CONSTRAINT fk_person FOREIGN KEY (person_ID) REFERENCES Person(person_ID)
);
With this, i expect to be able to enter null values for mentor_ID in my database but when I enter the query
insert into mentee(mentee_ID, mentor_ID, person_ID) VALUES (12313, null, 1)
I get the violation
ERROR: null value in column "mentor_id" of relation "mentee" violates not-null constraint
I was wondering how I could make it so I can insert null values for mentor_ID? I dont have it as not null in the table but it still says violating not null constraint.
Thank you
Because serial is not null.
serial is...
CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
Note the integer not null. This is because serial is to be used for primary keys, not foreign keys. Foreign keys are always assigned, they don't need to auto increment.
Use a plain integer.
mentor_ID integer references Mentor(mentor_ID)
Same for your other foreign keys.
Notes:
identity is the SQL standard way to do auto incremented primary keys.
You don't need to declare primary keys as unique, primary keys are already unique.
Unless there's a specific reason to constrain the size of a text field, use text. varchar and text only use the necessary amount of space for each row. "foo" will take the same amount of space in varchar(10) as in varchar(255). For example, there's no particular reason to limit the size of their linked in nor motivation.

Insert into PERSOANE table return violates check constraint but shouldn't

This is my creation script:
CREATE TABLE PERSOANE (
idPers numeric (5)
CONSTRAINT pk_persoane PRIMARY KEY,
NumePren varchar (30)
CONSTRAINT ck_nume CHECK (NumePren=LTRIM(INITCAP(NumePren))),
Loc varchar (30)
CONSTRAINT nn_loc NOT NULL
CONSTRAINT ck_loc CHECK (Loc=LTRIM(INITCAP(Loc))),
Jud varchar (25)
CONSTRAINT nn_jud NOT NULL
CONSTRAINT ck_jud CHECK (Jud=LTRIM(INITCAP(Jud))),
Tel numeric (10)
CONSTRAINT nn_tel NOT NULL,
E_mail varchar(254)
CONSTRAINT nn_e_mail NOT NULL
CONSTRAINT ck_e_mail CHECK (E_mail = LTRIM(E_mail))
);
When I try to insert values in the table I got error: new row for relation "persoane" violates check constraint "ck_jud" Here is my insert script:
INSERT INTO PERSOANE VALUES (11111, 'slimi marius', 'oras', 'judet', 0752361507, 'simic#yahoo.com');
Anyone has any suggestion how to fix this problem?
initcap() will change the first character to uppercase. So your check constraints on the columns numepren, loc and jud require you to enter values where the first character of every word is in uppercase. In the value 'jude' the first character is lowercase, so the check constraint is violated. You need to use 'Jude' instead. This is also true for the other columns you have defined:
INSERT INTO PERSOANE
(idpers, numepren, loc, jud, tel, e_mail)
VALUES
(11111, 'Slimi Marius', 'Oras', 'Judet', 0752361507, 'simic#yahoo.com');

Primary key for multiple columns in PostgreSQL?

How to provide primary key for multiple column in a single table using PostgreSQL?
Example:
Create table "Test"
(
"SlNo" int not null primary key,
"EmpID" int not null, /* Want to become primary key */
"Empname" varchar(50) null,
"EmpAddress" varchar(50) null
);
Note: I want to make "EmpID" also a primary key.
There can only be one primary key per table - as indicated by the word "primary".
You can have additional UNIQUE columns like:
CREATE TABLE test(
sl_no int PRIMARY KEY, -- NOT NULL due to PK
emp_id int UNIQUE NOT NULL,
emp_name text,
emp_addr text
);
Columns that are (part of) the PRIMARY KEY are marked NOT NULL automatically.
Or use a table constraint instead of a column constraint to create a single multicolumn primary key. This is semantically different from the above: Now, only the combination of both columns must be unique, each column can hold duplicates on its own.
CREATE TABLE test(
sl_no int, -- NOT NULL due to PK below
emp_id int , -- NOT NULL due to PK below
emp_name text,
emp_addr text,
PRIMARY KEY (sl_no, emp_id)
);
Multicolumn UNIQUE constraints are possible, too.
Aside: Don't use CaMeL-case identifiers in Postgres. Use legal, lower-case identifiers so you never have to use double-quotes. Makes your life easier. See:
Are PostgreSQL column names case-sensitive?
In case you want to specify the name of the primary key constraint:
CREATE TABLE test(
sl_no int not null,
emp_id int not null,
emp_name text,
emp_addr text,
constraint pk_test primary key (sl_no, emp_id)
);
Source: https://www.postgresqltutorial.com/postgresql-primary-key/

PostgreSQL foreign key not existing, issue of inheritance?

I am struggling with foreign keys in my DB, possibly it has something to do with inheritance?
So here's the basic setup:
-- table address
CREATE TABLE address
(
pk_address serial NOT NULL,
fk_gadmid_0 integer NOT NULL, -- this table already exists, no problem here
street character varying(100),
zip character varying(10),
city character varying(50),
public boolean,
CONSTRAINT address_primarykey PRIMARY KEY (pk_address),
CONSTRAINT gadmid_0_primarykey FOREIGN KEY (fk_gadmid_0)
REFERENCES adm0 (gadmid_0) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE address OWNER TO postgres;
-- table stakeholder (parent)
CREATE TABLE stakeholder
(
pk_stakeholder integer DEFAULT nextval('common_stakeholder_seq') NOT NULL,
fk_stakeholder_type integer NOT NULL, -- this table also exists, no problem here
name character varying(255) NOT NULL,
CONSTRAINT stakeholder_primarykey PRIMARY KEY (pk_stakeholder),
CONSTRAINT stakeholder_fk_stakeholder_type FOREIGN KEY (fk_stakeholder_type)
REFERENCES stakeholder_type (pk_stakeholder_type) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE stakeholder OWNER TO postgres;
-- table individual (child of stakeholder)
CREATE TABLE individual
(
firstname character varying(50),
fk_title integer, -- this table also exists, no problem here
email1 character varying (100),
email2 character varying (100),
phone1 character varying (50),
phone2 character varying (50),
CONSTRAINT individual_primarykey PRIMARY KEY (pk_stakeholder),
CONSTRAINT title_foreignkey FOREIGN KEY (fk_title)
REFERENCES title (pk_title) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
) INHERITS (stakeholder)
WITH (
OIDS=FALSE
);
ALTER TABLE individual OWNER TO postgres;
-- link between stakeholder and address
CREATE TABLE l_stakeholder_address
(
pk_l_stakeholder_address serial NOT NULL,
fk_stakeholder integer NOT NULL REFERENCES stakeholder,
fk_address integer NOT NULL REFERENCES address,
CONSTRAINT l_stakeholder_address_primarykey PRIMARY KEY (pk_l_stakeholder_address),
CONSTRAINT l_stakeholder_address_fk_stakeholder FOREIGN KEY (fk_stakeholder)
REFERENCES stakeholder (pk_stakeholder) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION,
CONSTRAINT l_stakeholder_address_fk_address FOREIGN KEY (fk_address)
REFERENCES address (pk_address) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE l_stakeholder_address OWNER TO postgres;
So far, no problem. Then I tried to add some values:
INSERT INTO individual (pk_stakeholder, fk_stakeholder_type, name, firstname, fk_title, email1, email2, phone1, phone2)
VALUES (1, 8, 'Lastname', 'Firstname', 1, 'me#you.com', '', '', '');
INSERT INTO address (pk_address, fk_gadmid_0, street, zip, city, public)
VALUES (1, 126, 'Address', '', 'City', FALSE);
INSERT INTO l_stakeholder_address (pk_l_stakeholder_address, fk_stakeholder, fk_address)
VALUES (DEFAULT, 1, 1);
And finally I end up having an error (SQL state 23503) saying that the key (fk_stakeholder)=(1) is not existing in table "stakeholder".
The first 2 inserts are fine, I can see them in the databases:
stakeholder:
pk_stakeholder | ...
----------------------
1 | ...
address:
pk_address | ...
--------------------
1 | ...
What am I doing wrong? I must admit that I am rather new to PostgreSQL (using 8.4) but I'm not even sure if that is an issue of PG at all, maybe I'm just lacking some basic database design understandings ...
Either way, by now I tried pretty much everything I could think of, I also tried to make the FK deferrable as in PostgreSQL : Transaction and foreign key problem but somehow that doesn't work either.
You can work around it using additional table individual_pks (individual_pk integer primary key) with all primary keys from both parent and child, which will be maintained using triggers (very simple — insert to individual_pks on insert, delete from it on delete, update it on update, if it changes individual_pk).
Then you point foreign keys to this additional table instead of a child. There'll be some small performance hit, but only when adding/deleting rows.
Or forget inheritance and do it the old way - simply one table with some nullable columns.
Your analysis is exactly right: It's because of the inheritance. When checking the foreign key, child tables are not considered.
In general, inheritance and foreign keys don't mix well in PostgreSQL. A major problem is that you can't have unique constraints across tables.
Reference