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

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)
);

Related

Error: there is no unique constraint in the referenced table "table_name" that matches the specified keys

CREATE TABLE IF NOT EXISTS ingredients
(
i_id SERIAL PRIMARY KEY,
i_name VARCHAR(100) NOT NULL
);
CREATE TABLE IF NOT EXISTS dishes
(
d_id SERIAL PRIMARY KEY,
d_name VARCHAR(100) NOT NULL
);
CREATE TABLE IF NOT EXISTS dishes_ingredients
(
di_id SERIAL PRIMARY KEY,
di_d_id INTEGER NOT NULL REFERENCES dishes(d_id),
di_i_id INTEGER NOT NULL REFERENCES ingredients(i_id),
di_i_weight DECIMAL NOT NULL
);
I get the error:
"there is no unique constraint in the referenced table
"dishes_ingredients" that matches the specified keys".
I have searched for this problem and notice that my two foreign keys in table "dishes_ingredients" are referencing two serial primary keys from tables "ingredients" and "dishes", and thus, they are by definition unique. What I am doing wrong?
This is the create statement for the table that references the table "dishes_ingredients":
CREATE TABLE IF NOT EXISTS ratings (
r_id SERIAL PRIMARY KEY,
r_c_id INTEGER REFERENCES customers(c_id),
r_d_id INTEGER REFERENCES dishes_ingredients(di_d_id),
r_value INTEGER NOT NULL
);

Design sql tables with list of foreign keys

I want to create an application for rotating pairs in a team every day. I need to store this in the database. Requirments are:
A team should be assigned to one ore more members.
Each team can have multiple tabs and different members allocate in them.(If team consist of 4 members for the particular tab only 3 should be part of it)
Each tab will have a pair of members or list of pairs per day stored.
I have ended up designing something like the example below:
create table if not exists team (
id serial not null primary key,
name text not null
);
create table if not exists member (
id serial not null primary key,
team_id integer references team(id),
nickname text
);
create table if not exists team_tab (
id bigserial not null primary key,
team_id integer references team(id) on delete cascade,
name text not null,
member_ids integer[],
);
create table if not exists team_tab_pairs (
id bigserial not null primary key,
team_tab_id integer not null references team_tab(id) on delete cascade,
tab_date date not null,
pair_ids integer[][],
);
I need an advice and suggestions how could I achieve this without having a list of references ids stored in the 2 tables below.
You need an extra table to design an M:N relationship. This is the case, for example, between "team tab" and "member". In addition to both main entities:
create table member (
id serial not null primary key,
team_id integer references team(id),
nickname text
);
create table team_tab (
id bigserial not null primary key,
team_id integer references team(id) on delete cascade,
name text not null
);
...you'll need to create a table to represent the M:N relationship, as in:
create table team_tab_member (
team_tab_id bigint not null,
member_id int not null,
primary key (team_tab_id, member_id) -- optional depending on the model
);

POSTGRESQL. Insert or update on table violates foreign key constraint

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.

Postgresql multiple tables with same foreign key unique constraint

I have following tables on PostgreSQL 9.4
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
email CHARACTER VARYING NOT NULL,
password CHARACTER VARYING NOT NULL
);
CREATE TABLE "dealer" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user" (id) ON DELETE RESTRICT
);
CREATE TABLE "affiliate" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES "user" (id) ON DELETE RESTRICT
);
Is it possible to force user_id value to be unique across tables dealer and affiliate?
There are different setups to use for inheritance in SQL and for this you could just use an integer column type in the table user that marks the type of the user and would reference to table user_type (id,name) that would have the values 1,dealer and 2,affiliate:
CREATE TABLE user_type (
id INTEGER PRIMARY KEY, --could be SERIAL
name text
);
INSERT INTO user_type VALUES (1,'dealer'), (2, 'affiliate');
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
email CHARACTER VARYING NOT NULL,
password CHARACTER VARYING NOT NULL,
user_type INTEGER REFERENCES user_type NOT NULL,
UNIQUE(id,user_type)
);
This in itself wouldn't force uniqueness across tables so after implementing this you would have the following options:
Drop the tables dealer and affiliate - you won't need them if you rely on the type field to see which one the user is.
If you have to keep those inherited tables you can:
Use triggers - these triggers check the uniqueness and would be actived on INSERT or UPDATE
Another (a bit clumsy) solution: add user_type field to both subtables like this:
CREATE TABLE "dealer" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
user_type INTEGER NOT NULL DEFAULT 1 check (user_type = 1),
FOREIGN KEY (user_id,user_type) REFERENCES "user"(id,user_type) ON DELETE RESTRICT
);
CREATE TABLE "affiliate" (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
user_type INTEGER NOT NULL DEFAULT 2 check (user_type = 2),
FOREIGN KEY (user_id,user_type) REFERENCES "user"(id,user_type) ON DELETE RESTRICT
);
The checks and foreign keys together make sure you cannot have both types of user in the main table. Note that user_id might be used as the PRIMARY KEY in the subtables too. Currently a row in user might have several dealer rows linked to it so at least you might want to set user_id foreign keys in subtables as UNIQUE.

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"