Postgres cannot create foreign key to serial - postgresql

I'm trying to create some Postgres tables, one has a foreign key on anothers' index:
CREATE TABLE Foo (ID SERIAL PRIMARY KEY);
CREATE TABLE File (FooId TEXT NOT NULL REFERENCES Foo (ID));
But it results in ERROR: foreign key constraint file_fooid_fkey cannot be implemented

Appears the types have to "match" or you'll get that error.
This works (change to int to match the size/type of SERIAL KEY which is an INT):
CREATE TABLE Foo (ID SERIAL PRIMARY KEY);
CREATE TABLE File (FooId INT NOT NULL REFERENCES Foo (ID));

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.

PostgreSQL - Common autoincrement with inherited tables

I'm currently trying the inheritance system with PostgreSQL but I have a problem with the auto-increment index in my child tables.
I have three tables: "Currency", "Crypto" and "Stable"
CREATE TABLE IF NOT EXISTS public.currency
(
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
name VARCHAR(30) UNIQUE NOT NULL,
symbol VARCHAR(10) UNIQUE NOT NULL,
);
CREATE TABLE IF NOT EXISTS public.stable (id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY) INHERITS (public.currency);
CREATE TABLE IF NOT EXISTS public.crypto (id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY) INHERITS (public.currency);
I insered my data like this:
INSERT INTO public.stable (name, symbol) VALUES ('Euro', '€'), ('Dollar', '$'), ('Tether', 'USDT');
INSERT INTO public.crypto (name, symbol) VALUES ('Bitcoin', 'BTC'), ('Ethereum', 'ETH'), ('Litcoin', 'LTC');
But this is my problem: I would like to have a unique identifier that increments itself through my parent table "Currency".
When I select, I have (take a look in my id: 1,2,3,1,2,3):
But, Is it possible to have something like this instead (1,2,3,4,5,6):
Is it a problem in my primary key?
Thank you
We can try to use create sequence to set row numbers for sharing between multiple tables.
define a new sequence generator
create sequence n_id;
Then we can use this sequence as below, sharing this sequence for those three tables.
create sequence n_id;
CREATE TABLE IF NOT EXISTS currency
(
id INT default nextval('n_id') PRIMARY KEY,
name VARCHAR(30) UNIQUE NOT NULL,
symbol VARCHAR(10) UNIQUE NOT NULL
);
CREATE TABLE IF NOT EXISTS stable (id INT default nextval('n_id') PRIMARY KEY) INHERITS (currency);
CREATE TABLE IF NOT EXISTS crypto (id INT default nextval('n_id') PRIMARY KEY) INHERITS (currency);
sqlfiddle

How do I make a foreign key that can be two different data types without using CREATE CAST? [duplicate]

I have three database tables: ALIENS, MONSTERS, and TROPHIES.
Each ALIEN can have multiple TROPHIES.
Each MONSTER can have multiple TROPHIES.
Each TROPHY must have exactly one WINNER (ALIEN XOR MONSTER).
Is there a way to have a foreign key in the TROPHY table that references the primary key of either an ALIEN or a MONSTER?
Or is it easier to simply have two tables: an ALIEN_TROPHY table and a MONSTER_TROPHY table (even though they would be identical)?
You could create two foreign keys with a check constraint that says exactly one is empty:
create table alien (id int primary key);
create table monster (id int primary key);
create table trophy (id int primary key,
alien_id int references alien(id),
monster_id int references monster(id),
check (alien_id is null <> monster_id is null)
);

PostgreSQL - Foreign Key References Mutually Exclusive Tables

I have three database tables: ALIENS, MONSTERS, and TROPHIES.
Each ALIEN can have multiple TROPHIES.
Each MONSTER can have multiple TROPHIES.
Each TROPHY must have exactly one WINNER (ALIEN XOR MONSTER).
Is there a way to have a foreign key in the TROPHY table that references the primary key of either an ALIEN or a MONSTER?
Or is it easier to simply have two tables: an ALIEN_TROPHY table and a MONSTER_TROPHY table (even though they would be identical)?
You could create two foreign keys with a check constraint that says exactly one is empty:
create table alien (id int primary key);
create table monster (id int primary key);
create table trophy (id int primary key,
alien_id int references alien(id),
monster_id int references monster(id),
check (alien_id is null <> monster_id is null)
);

JSON foreign keys in PostgreSQL

Is it possible to assign a foreign key to a json property in PostgreSQL? Here is an example what I would like to achieve, but it doesn't work:
CREATE TABLE Users (Id int NOT NULL PRIMARY KEY);
CREATE TABLE Data (
Id int NOT NULL PRIMARY KEY,
JsonData json NOT NULL, -- [{Id: 1, somedata: null},{Id: 2, somedata: null}, ...]
CONSTRAINT FK_Users_Data FOREIGN KEY (JsonData->Id) REFERENCES Users(Id) -- this constraint will fail
);
It is not possible, and may not ever be possible, to assign a foreign key to a json property. It'd be a major and quite complicated change to PostgreSQL's foreign key enforcement. I don't think it's impossible to do, but would face similar issues to those experienced by the foreign-keys-to-arrays patch.
With 9.4 it'll be possible to make a whole json object a foreign key as jsonb supports equality tests. In 9.3 you can't even do that.
Here's a little SPI function have_ids which I use for an integrity constraint on a one-to-many relationship with a jsonb column
CREATE TABLE foo (
id INTEGER NOT NULL
)
CREATE TABLE bar (
foo_ids pg_catalog.jsonb DEFAULT '[]'::jsonb NOT NULL,
CONSTRAINT bar_fooids_chk CHECK (have_ids ('foo', foo_ids))
)
With a couple of triggers on foo it's almost as good as a foreign key.
The foreign key parameter must be a column name:
http://www.postgresql.org/docs/current/static/sql-createtable.html
You will have to normalize
create table user_data (
id int not null primary key,
user_id int not null,
somedata text,
constraint fk_users_data foreign key (user_id) references Users(Id)
);
Yes it is possible but you will have to store another value. If you change your schema to:
CREATE TABLE Users (Id int NOT NULL PRIMARY KEY);
CREATE TABLE Data (
Id int NOT NULL PRIMARY KEY,
JsonData json NOT NULL,
UserId int generated always as ((JsonData->>'Id')::int) stored references Users(Id)
);
INSERT INTO Users VALUES (1);
Foreign key that doesn't exist:
INSERT INTO Data VALUES (1, '{"Id": 3}');
Returns the error:
ERROR: insert or update on table "data" violates foreign key constraint "data_userid_fkey" DETAIL: Key (userid)=(3) is not present in table "users".
Foreign key that does work:
INSERT INTO Data VALUES (1, '{"Id": 1}');