PostgresQL Foreign Key Syntax Error - sql

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

Related

Upgrading H2 database gives constraint not found exception

I am trying to upgrade my H2 dependency which I use on my testcases from 1.4.200 to 2.1.212 but it gives a constraint not found exception when I try to do so. The SQL is like this:
CREATE TABLE itineraries
(
id SERIAL,
itinerary_id VARCHAR(36) NOT NULL,
user_id VARCHAR(36) NOT NULL,
created_at TIMESTAMP,
version INTEGER DEFAULT 1,
update_timestamp BIGINT,
CONSTRAINT itineraries_pkey PRIMARY KEY (itinerary_id, user_id),
CONSTRAINT itineraries_user_id_fkey FOREIGN KEY (user_id) REFERENCES users (user_id)
);
CREATE UNIQUE INDEX itineraries_id_key ON itineraries (id);
CREATE TABLE subscriptions
(
subscription_id VARCHAR(36) PRIMARY KEY NOT NULL,
type VARCHAR(10) NOT NULL,
status VARCHAR(20),
last_updated TIMESTAMP NOT NULL,
itinerary_id VARCHAR(36) NOT NULL,
itinerary_db_id BIGINT,
CONSTRAINT subscriptions_it_itinerary_id_fkey FOREIGN KEY (itinerary_db_id) REFERENCES itineraries (id)
);
Which gives the following error:
Cause: org.h2.jdbc.JdbcSQLSyntaxErrorException: Constraint "PRIMARY KEY | UNIQUE (ID)" not found; SQL statement:
What needs to be changed about the SQL? Since to me it seems like the unique index is created before the create table query.
Unique indexes and unique constraints are different things.
You need to create a constraint and you don't need an index in H2, because unique constraints in H2 create indexes automatically.
CREATE TABLE itineraries
(
id BIGINT GENERATED BY DEFAULT AS IDENTITY CONSTRAINT itineraries_id_key UNIQUE,
…
I changed PostgreSQL-compatibility SERIAL to standard-compliant BIGINT GENERATED BY DEFAULT AS IDENTITY, because SERIAL is a legacy data type and it creates an INTEGER column, but it is referenced by subscriptions.itinerary_db_id with BIGINT data type, it isn't strictly required, but normally you should use the same data type for both columns, you can choose BIGINT, INTEGER or some other numeric type.
Usually it is more reasonable to create a primary key constraint for id column and a unique constraint for (itinerary_id, user_id), but you may have own reasons for such schema.
Also VARCHAR(36) looks like a some data type for UUID values, H2 has more efficient specialized UUID data type for this purpose.

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.

Why PSQL create table returns [42P01] ERROR: relation does not exist

I'm new to SQL. I was trying to run sql schema, here is a part of code
create table PageColours (
id serial,
userID serial references users(id),
--references users(id),
isTemplate boolean default'false',
name NameValue not null unique,
primary key (id)
);
create table People (
id serial,
email EmailValue not null unique,
givenName NameValue not null,
familyName NameValue,
invitedID serial references Events(id),
attendedID serial references Events(id),
primary key (id)
);
create table users(
id serial
references People(id),
passWord varchar not null,
BillingAddress serial not null
references Places(id),
HomeAddress serial
references Places(id),
ListID serial
references ContactLists(id),
ColorID serial
references PageColours(id),
primary key (id)
);
It returns[2020-07-03 15:28:19] [42P01] ERROR: relation "people" does not exist
[2020-07-03 15:28:19] [42P01] ERROR: relation "users" does not exist
In fact all foreign key reference table reference not exist. When i remove the reference, the table can be created, can someone please help me ?
The script is run sequentially. So when the pagecolours table is created, the users table does not yet exist and thus the references users fails.
You need to re-order the script, so that the users table is created first. But as you have a circular reference (users references pagecolours and pagecolours references users) you need to create the tables without an "inline" reference, and then at the end of the script you need to run an ALTER TABLE to create the foreign keys.
But having a circular reference like that, is usually not a good idea. But if you are 100% sure you need it, you should at least declare the foreign keys as deferrable, to make inserting rows easier.
Also: serial is not a datatype. A foreign key column that references a serial column should be defined as an integer. In general it is recommended to move away from serial and use integer generated always as identity instead.

Foreign key in the first table

I have a question about foreign keys.
How does it work when I want to add a foreign key to the first table that I make that references to the primary key of the second table I create?
CREATE TABLE table1
(
name_id INT NOT NULL,
team TEXT REFERENCES table2(team_id),
PRIMARY KEY(name_id)
);
CREATE TABLE table2
(
team_id INT NOT NULL,
teamname TEXT,
PRIMARY KEY(team_id)
);
If I try the code above I get the following error:
ERROR: relation "" does not exist
Thanks in advance.
Either create the second table first. Or use alter table. That is, create the first table without the reference and then do:
alter table table1 add constraint fk_table1_team
foreign key (team_id) REFERENCES table2(team_id);
The declaration for table1 would be:
CREATE TABLE table1 (
name_id INT NOT NULL,
team_id INT,
PRIMARY KEY(name_id)
);
The reference between the tables should be on the primary key and certainly not on a character column, if an integer is available.
here's the syntax of creating a table with Foreign key:
CREATE TABLE table11
(
name_id INT NOT NULL,
team INT,
PRIMARY KEY(name_id),
foreign key(team) references table22(team_id)
);
CREATE TABLE table22
(
team_id INT NOT NULL,
teamname TEXT,
PRIMARY KEY(team_id)
);
but there was another problem. a foreign key from a child table cannot reference to a primary key from a parent folder if they do not contain the same type. in your code team was of TEXT and team_id was of INT which cannot be.

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