Does postgresql require unique constraint names when defining FOREIGN KEYS - postgresql

Here is my schema for database tables:
CREATE TABLE users (
user_id INTEGER NOT NULL,
device_id INTEGER,
user_points INTEGER,
cookie VARCHAR,
PRIMARY KEY (user_id)
);
CREATE TABLE admins (
admin_id INTEGER NOT NULL,
username VARCHAR,
password VARCHAR
);
CREATE TABLE admin_adventure (
adventure_id INTEGER NOT NULL,
admin_id INTEGER,
PRIMARY KEY (adventure_id)
);
CREATE TABLE adventures (
adventure_id INTEGER NOT NULL,
prize_id INTEGER,
novella_id INTEGER,
PRIMARY KEY (adventure_id)
);
Here I'm trying to define FOREIGN KEYS:
ALTER TABLE admin_adventure ADD FOREIGN KEY ( admin_id ) REFERENCES admins ( admin_id );
ALTER TABLE admin_adventure ADD FOREIGN KEY ( adventure_id ) REFERENCES adventures ( adventure_id );
And here is the error I get when trying to migrate with Flyway:
ERROR: there is no unique constraint matching given keys for
referenced table "admins"
Can someone explain what I'm doing wrong and why I get this error?

The error message is complaining that you are trying to link a foreign key to a column in another table which is not unique (e.g. a primary key). Try making the admin_id column in the admins table a primary key:
CREATE TABLE admins (
admin_id INTEGER NOT NULL,
username VARCHAR,
password VARCHAR,
PRIMARY KEY (admin_id)
);

Like the documentation says:
A foreign key must reference columns that either are a primary key or form a unique constraint.
So you must either
ALTER TABLE admins ADD PRIMARY KEY (admin_id);
or
ALTER TABLE admins ADD UNIQUE (admin_id);

Related

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.

PostgreSQL ERROR: relation "XXX" does not exist and unsure why

I run my code and get the error in PostgreSQL. I have created multiple tables and the first seems to work while the others don't.
create table people (
id serial,
family_names text,
given_names text,
displayed_names text,
email_address text,
primary key (id)
);
create table users (
userid integer,
website text,
date_registered date,
gender GenderValue,
birthday date,
password text,
portrait integer,
primary key (userid),
foreign key (userid) references people(id),
foreign key (portrait) references photos(photoid)
);
create table photos (
photoid serial,
title TitleValue,
date_uploaded date,
date_taken date,
description text,
technical_details text,
safety_level safetyLevel,
visibility visibilityLevel,
owns integer,
primary key (photoid),
foreign key (owns) references users(userid)
);

Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'questions_ibfk_1' in the referenced table 'category'

cannot add foreign key constraint to table
create table users
(
user_id int auto_increment primary key not null,
username varchar(50) unique null ,
email varchar(50) unique ,
passwords varchar(50) not null,
login_status boolean not null
);
create table category (
category_id int primary key not null,
category_name varchar(50) not null
);
create table answers (
id_answer int auto_increment primary key not null,
answer boolean not null
);
create table questions (
question_id int primary key not null,
category_name varchar(50) not null,
content varchar(50) not null ,
foreign key (category_name) references category (category_name)
);
You get this error because there's no index on category_name in the category table. Change that CREATE statement as follows:
create table category (
category_id int primary key not null,
category_name varchar(50) not null,
KEY category_name_index (category_name)
);
From the docs (8.0 version, but the statement is true for older versions):
MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.
Also, you're using a varchar(50) as your foreign key, which is not usually a great idea for a variety of reasons. You probably want to use a numeric value, such as category_id, instead.

How to add a foreign key for table B by referring of table A and foreign key for table A by referring table B in PostgreSQL?

I need to add a foreign keys for two tables each other. Can this be done ?
As an example:
CREATE SCHEMA IF NOT EXISTS schema1;
CREATE TABLE schema1.tableA
(
id serial NOT NULL,
tableB_id integer,
PRIMARY KEY (id),
FOREIGN KEY (tableB_id) REFERENCES schema1.tableB (id)
);
CREATE TABLE schema1.tableB
(
id serial NOT NULL,
tableA_id integer,
PRIMARY KEY (id),
FOREIGN KEY (tableA_id) REFERENCES schema1.tableA(id)
);
Above query causes an error !
ERROR: relation "schema1.tableb" does not exist SQL state: 42P01
Can this be done or is there any better solution?
I'am using PostgreSQL version 10.5 and pgAdmin 3.6
Add the foreign keys after creating both tables:
CREATE SCHEMA IF NOT EXISTS schema1;
CREATE TABLE schema1.tableA
(
id serial NOT NULL,
tableB_id integer,
PRIMARY KEY (id)
);
CREATE TABLE schema1.tableB
(
id serial NOT NULL,
tableA_id integer,
PRIMARY KEY (id)
);
ALTER TABLE schema1.tablea
add FOREIGN KEY (tableB_id) REFERENCES schema1.tableB (id);
ALTER TABLE schema1.tableb
add foreign key (tableA_id) REFERENCES schema1.tableA(id);

Foreign keys in Postgres

i´ve got a problem with foreign keys, it´s an strange problem.
First table:
CREATE TABLE adjunto
(
id serial NOT NULL,
codigo text,
descripcion text,
usuario integer,
file integer,
nombre text,
propiedades hstore,
CONSTRAINT adjunto_pkey PRIMARY KEY (id ),
CONSTRAINT adjunto_file_fkey FOREIGN KEY (file)
REFERENCES file (file_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
) WITH (
OIDS=FALSE
);
Second table:
CREATE TABLE adjunto_coleccion_privada
(
id serial NOT NULL,
adjunto integer,
coleccion integer,
CONSTRAINT adjunto_coleccion_privada_pkey PRIMARY KEY (id ),
CONSTRAINT adjunto_coleccion_privada_adjunto_fkey FOREIGN KEY (adjunto)
REFERENCES adjunto (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT adjunto_coleccion_privada_coleccion_fkey FOREIGN KEY (coleccion)
REFERENCES coleccion (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
Command:
INSERT INTO adjunto_coleccion_privada (adjunto, coleccion)
VALUES (600, 2) RETURNING id
Values 600 and 2 exist in both tables, adjunto and colecion.
Detailed error:
Mensaje: ERROR: insert or update on table "adjunto_coleccion_privada"
violates foreign key
constraint "adjunto_coleccion_privada_adjunto_fkey"
Detail: Key (adjunto)=(600) is not present in table "adjunto".
I tested your code (I dropped the adjunto_coleccion_privada_coleccion_fkey constraint since referred table does not exist in your pasted code).
I see no problem at all.
Are you really sure that there is a record with id = 600 in the adjunto table?