POSTGRESQL. Insert or update on table violates foreign key constraint - sql

I am new in Posgresql. I have 5 tables and I am trying to INSERT properties to tables. When I tried to Insert 2nd time, I have this error in 'pgadmin'.
ERROR: insert or update on table "question" violates foreign key constraint "question_id_difficulty_fkey" DETAIL: Key (id_difficulty)=(9) is not present in table "difficulty". SQL state: 23503.
my schema is here
id SERIAL PRIMARY KEY,
name varchar
);
CREATE TABLE question (
id SERIAL PRIMARY KEY,
text varchar,
correct_answer varchar,
incorrect_answer1 varchar,
incorrect_answer2 varchar,
incorrect_answer3 varchar,
id_difficulty SERIAL REFERENCES difficulty(id),
id_category SERIAL REFERENCES category (id),
id_creator SERIAL REFERENCES game (id)
);
CREATE TABLE difficulty (
id SERIAL PRIMARY KEY,
name varchar
);
CREATE TABLE category (
id SERIAL PRIAMRY KEY,
name varchar
);
CREATE TABLE user (
id SERIAL PRIMARY KEY,
name varchar
)

You would need a corresponding entry in the difficulty table with an id of 9, so that a referencing id_difficulty column in the question table.
For example, if your difficulty table contained:
id | name
----+----------------
1 | easy
2 | reasonable
3 | difficult
4 | very difficult
5 | impossible
You could only set id_difficulty for rows in the question table to one of those id values. If you set 6, or 12 or anything other than 1 to 5, it would fail because the values are constrained by the values in the foreign key.
The id_difficulty, id_category and id_creator columns shouldn't be using serial, so these should have their defaults dropped:
ALTER TABLE question ALTER COLUMN id_difficulty DROP DEFAULT;
ALTER TABLE question ALTER COLUMN id_category DROP DEFAULT;
ALTER TABLE question ALTER COLUMN id_creator DROP DEFAULT;

Postgres now recommends using generated always as instead of serial. If you do this, then the types will align much more simply:
CREATE TABLE question (
id int generated always as identity PRIMARY KEY,
text varchar,
correct_answer varchar,
incorrect_answer1 varchar,
incorrect_answer2 varchar,
incorrect_answer3 varchar,
id_difficulty int REFERENCES difficulty(id),
id_category int REFERENCES category (id),
id_creator int REFERENCES game (id)
);
CREATE TABLE difficulty (
id int generated always as identity PRIMARY KEY,
name varchar
);
This makes what is happening much clearer. The data type for a foreign key reference needs to match the data type of the primary key. Postgres knows that serial is really int. But using generated always, it is obvious that they are the same.
In addition, generated always as is more consistent with standard SQL.

Related

Sql creating table consisting of keys from other tables

this is probably a simple question but I am quite new to SQL and databases, so I have been following this site: https://www.postgresqltutorial.com/postgresql-foreign-key/ to try and create a table that consist of primary keys from other tables.
Here I have the structure of the database in an excel overview. With colors showing the relations. i am having problems with the One-To-Many tables. As I get the same error every time "ERROR: column "id" referenced in foreign key constraint does not exist
SQL state: 42703".
The SQL query:
DROP TABLE IF EXISTS ingredient_to_unit_relations;
DROP TABLE IF EXISTS ingrediens;
CREATE TABLE ingrediens (
id serial,
name_of_ingredient varchar(255),
price_per_unit int,
PRIMARY KEY (id)
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id
FOREIGN KEY (id)
REFERENCES ingrediens (id)
);
You need to define the column in order to declare it as a foreign key:
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY,
ingredient_id int,
PRIMARY KEY (ingredient_relation_id),
constraint Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingrediens (id)
);
I might recommend some somewhat different naming conventions (I changed the name id in the table above):
CREATE TABLE ingredients (
ingredient_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name varchar(255),
price_per_unit int
);
CREATE TABLE ingredient_to_unit_relations (
ingredient_relation_id int GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
ingredient_id int,
CONSTRAINT Fk_ingredient_id FOREIGN KEY (ingredient_id) REFERENCES ingredients (ingredient_id)
);
Notes:
I am a fan of naming primary keys after the table they are in. That way, foreign keys and primary keys usually have the same name (and you can use using if you choose).
Avoid SERIAL. GENERATED ALWAYS AS IDENTITY is now recommended.
You can inline primary key constraints (as well as other constraints).
There is not generally a need to repeat the table name in a column (other than the primary key). So, name instead of name_of_ingredient.
Using int for a monetary column is suspicious. It doesn't allow smaller units. That might work for some currencies but in general I would expect a numeric/decimal type.

PostgresQL Foreign Key Syntax Error

When attempting to create the second table in this respective database, I'm getting the following error message:
ERROR: syntax error at or near "REFERENCES"
LINE 3: master_directory REFERENCES auth_table (directory),
Here's the database structure that I attempted to create:
CREATE TABLE auth_table (
id SERIAL PRIMARY KEY,
directory VARCHAR,
image VARCHAR
)
CREATE TABLE master_table (
id SERIAL PRIMARY KEY,
master_directory references auth_table (directory),
master_image references auth_table (image)
)
Any reason why I'm receiving that error? Any help would be appreciated!
You've left the data type off, but that syntax error is the least of your problems.
Your foreign key references need to refer to unique column(s). So "auth_table" probably needs to be declared one of these ways. (And you probably want the second one, if your table has something to do with the paths to files.)
CREATE TABLE auth_table (
id SERIAL PRIMARY KEY,
directory VARCHAR not null unique,
image VARCHAR not null unique
);
CREATE TABLE auth_table (
id SERIAL PRIMARY KEY,
directory VARCHAR not null,
image VARCHAR not null,
unique (directory, image)
);
Those unique constraints mean quite different things, and each requires a different foreign key reference. Assuming that you want to declare "auth_table" the second way, "master_table" probably ought to be declared like one of these. (Deliberately ignoring cascading updates and deletes.)
CREATE TABLE master_table (
master_directory varchar not null,
master_image varchar not null,
primary key (master_directory, master_image),
foreign key (master_directory, master_image)
references auth_table (directory, image)
);
CREATE TABLE master_table (
id integer primary key,
foreign key (id) references auth_table (id)
);

How do I make a serial field auto increment and be a foreign key - Postgres

I have 2 tables and I am trying to create a Foreign Key between the two. Here is the structure of my tables:
create table users (
id serial,
user_name varchar(50)
);
create table playlists (
id serial,
user_id integer references users(id)
);
I keep getting this error:
ERROR: there is no unique constraint matching given keys for referenced table "users"
Why is there not a unique constraint? If I create the id in the users table as integer PRIMARY KEY, then everything works fine. How do I fix this where the users id auto increments and can be the FK in the playlists table?
Creating a column of type serial doesn't make it the primary key or constraint it in any way. serial just creates an integer column, creates a sequence, and attaches the sequence to the column to provide default values. From the fine manual:
In the current implementation, specifying:
CREATE TABLE tablename (
colname SERIAL
);
is equivalent to specifying:
CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
If you want your id serial columns to be primary keys (which you almost certainly do), then say so:
create table users (
id serial not null primary key,
user_name varchar(50)
);
create table playlists (
id serial not null primary key,
user_id integer references users(id)
);

Insert null value in an association table

I have a problem with something in SQL, let's see an example of database :
CREATE TABLE person( //Employee
pe_id PRIMARY KEY NOT NULL AUTO_INCREMENT,
pe_name VARCHAR(20),
pe_office VARCHAR(20)
);
CREATE TABLE project( //Mission
pr_id PRIMARY KEY NOT NULL AUTO_INCREMENT,
pr_name VARCHAR(20),
pr_status VARCHAR(15)
);
CREATE TABLE techno( //Programming language
te_id PRIMARY KEY NOT NULL AUTO_INCREMENT,
te_name VARCHAR(20)
);
CREATE TABLE job( //developer, manager, ...
jo_id PRIMARY KEY NOT NULL AUTO_INCREMENT,
jo_name VARCHAR(20)
);
I would like to assign persons on projects for a job using technos.
For example, Rob works as a developer and project manager on the projet #13 with AngularJS and HTML.
So I created this table :
CREATE TABLE assignment(
pe_id INT,
pr_id INT,
te_id INT,
jo_id INT,
as_days INT, //Days of work
PRIMARY KEY(pe_id, pr_id, tr_id, jo_id),
CONSTRAINT fk_as_pe_id FOREIGN KEY(pe_id) REFERENCES person(pe_id),
CONSTRAINT fk_as_pr_id FOREIGN KEY(pr_id) REFERENCES project(pr_id),
CONSTRAINT fk_as_te_id FOREIGN KEY(te_id) REFERENCES techno(te_id),
CONSTRAINT fk_as_jo_id FOREIGN KEY(jo_id) REFERENCES job(jo_id)
);
I would like to have the ability to assign a developer with somes technos to a project without knowing who exaclty, like this:
INSERT INTO assignment(pr_id,te_id,jo_id,as_days) VALUES(1,2,3,4); //No person!
We suppose that this values exists in project, techno and job tables.
But it seems that I can not insert this, probably because I do not define person's ID (which is in the primary key).
How can I do this ?
Hope I'm understandable :)
You solve this problem by not having this as a primary key. Primary keys cannot be NULL or, if they're composite primary keys, cannot contain NULL. Make it a unique index instead. Create an autonumber field for the primary key. I think this is better solution in your case
Primary Key:
Can be only one in a table
It never allows null values
Primary Key is unique key identifier and can not be null and must be unique.
Unique Key:
Can be more than one unique key in one table.
Unique key can have null values(only single null is allowed).
It can be a candidate key
Unique key can be null and may not be unique.
Maybe you should do this:
Before insert disable constraint:
ALTER INDEX fk_as_pe_id ON assignment
DISABLE;
After insert enable it:
ALTER INDEX fk_as_pe_id ON assignment
REBUILD;
Another alternate way is, if it is possible to alter table structure, just exclude pe_id from the composite primary key in assignment table

Key in same table in postgres?

I'm trying to create a hireiarchial table in postgres. I'm using the adjacent list-approach. My question is, how should I reference the ID of the same table when creating the data-model?
create table nodes (
id serial primary key,
parentid WHAT GOES HERE?
name varchar,
);
You can do:
create table nodes (
id serial primary key,
parentid integer references nodes(id),
name varchar
);
These are called "self-referencing tables"