Postgresql - there is not unique constraint matching given keys for referenced table; referencing a key from own table - postgresql

I created a table (team) which has a composite primary key composed of the id, project id, and a user id. Each primary key references a key in some other table except for the id. Now I want to add a key (team_id) that references the own id of the team because i want to cater a sub team and this team_id will contain the id of the parent team.
I encountered an error: 'there is no unique constraint matching given keys for referenced table "team"'.
Am I wrong to understand that each possible combination of each of the keys in the composite primary key is the team's unique constraint?
What am I missing?
CREATE TABLE team (
id varchar NOT NULL,
project_id varchar NOT NULL, -- team should always have associated project
user_id varchar NOT NULL, -- team member id
team_id varchar, -- parent team id
create_date date NOT NULL,
create_time time NOT NULL,
name varchar,
description text,
PRIMARY KEY (id, project_id, user_id),
FOREIGN KEY (project_id) REFERENCES project (id)
ON UPDATE CASCADE
ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES person (id)
ON UPDATE CASCADE
ON DELETE CASCADE,
FOREIGN KEY (team_id) REFERENCES team (id)
ON DELETE CASCADE
ON UPDATE CASCADE
);

parent_team_id varchar,
parent_team_project_id varchar,
parent_team_user_id varchar,
foreign key (
parent_team_id, parent_team_project_id, parent_team_user_id
) references team (id, project_id, user_id);
But the primary key is strange. Are you sure?

Related

Trying to make a UNIQUE KEY become a FOREIGN KEY, but it says error

I created this table. I want the user_id to be inserted without someone having to type it. Can someone help me? When I tried to create it it shows this error:
Why is the fk_id being compared to cpf?
CREATE TABLE code.went_to
(
user_id INTEGER,
cpf VARCHAR(11) NOT NULL,
cep VARCHAR(8) NOT NULL,
date DATE,
contact_id INTEGER,
CONSTRAINT fk_id
FOREIGN KEY (user_id) REFERENCES code.user,
CONSTRAINT fk_cpf_user
FOREIGN KEY (cpf) REFERENCES code.user,
CONSTRAINT fk_cep_place
FOREIGN KEY (cep) REFERENCES code.place,
CONSTRAINT fk_tipo_id
FOREIGN KEY (tipo_id) REFERENCES code.contact,
EXCLUDE USING gist (cpf WITH =, cep WITH =, daterange(data, (data + interval '4 months')::date) WITH &&),
EXCLUDE USING gist (cep WITH =, contact_id WITH =, daterange(data, (data + interval '1 months')::date) WITH &&)
);
The table that user_id comes from:
CREATE TABLE code.user
(
user_id SERIAL NOT NULL,
cpf VARCHAR(11) NOT NULL,
name CHAR(75) NOT NULL,
nick_name VARCHAR(15),
CONSTRAINT pk_cpf PRIMARY KEY(cpf),
CONSTRAINT un_id UNIQUE (id),
CONSTRAINT un_nick_name UNIQUE (nick_name)
);
Sorry if its stated weird, my English is not the best. But essentially the question should be:
How could I import data (user_id) from one table (user) into another table (went_to) based on the primary key (cpf)?
If you don't specify a target column, the references clause assumes the primary key of the target table. There is no matching on the name happening.
You need to include the column of the unique key in your foreign key definition:
CONSTRAINT fk_id FOREIGN KEY (user_id) REFERENCES code."user"(user_id)
To make things less confusing, I would also do that for the FK that references the PK
CONSTRAINT fk_cpf_user FOREIGN KEY (cpf) REFERENCES code."user"(cpf),

there is no unique constraint matching given keys for referenced table "category"?

I'm trying to define more than one foreign key in the process table. but I am getting the error that the columns I am trying to define as foreign key are not 'unique value'.
For this, I wanted to define id and name columns as primary keys in category and subject tables. However, when I want to create the process table, I still get this error." there is no unique constraint matching given keys for referenced table "category"
I have researched and continue to do so on Stackoverflow and many more. but I couldn't figure it out with solutions or viewpoints of the issues that got the same error I was facing. Maybe there is something I'm not seeing.
first table;
CREATE TABLE category(
category_id INT GENERATED ALWAYS AS IDENTITY,
category_name VARCHAR(210),
category_description TEXT,
CONSTRAINT category_pk PRIMARY KEY(category_id,category_name)
);
second table;
CREATE TABLE subject(
subject_id INT GENERATED ALWAYS AS IDENTITY,
subject_name VARCHAR(210),
subject_description TEXT,
CONSTRAINT subject_pk PRIMARY KEY(subject_id,subject_name)
);
I tried that too but I keep getting the same error
ALTER TABLE category ADD CONSTRAINT some_constraint PRIMARY KEY(category_id,category_name);
third table;
CREATE TABLE process(
process_id INT GENERATED ALWAYS AS IDENTITY,
fk_category_id INTEGER,
fk_subject_id INTEGER,
FOREIGN KEY(fk_category_id) REFERENCES category(category_id) ON DELETE CASCADE ON UPDATE
CASCADE,
FOREIGN KEY(fk_subject_id) REFERENCES subject(subject_id) ON DELETE CASCADE ON UPDATE
CASCADE
);
In your FOREIGN KEY declaration either:
Include both the columns that make up the PRIMARY KEY on category and subject e.g. ... REFERENCES category(category_id, category_name) ...
OR
Do not refer to any column and let the FK pick up the PK automatically e.g. ... REFERENCES category ON DELETE ....
I am going to say that what you are really after is:
CREATE TABLE category(
category_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
category_name VARCHAR(210) UNIQUE,
category_description TEXT
);
CREATE TABLE subject(
subject_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
subject_name VARCHAR(210) UNIQUE,
subject_description TEXT
);
CREATE TABLE process(
process_id INT GENERATED ALWAYS AS IDENTITY,
fk_category_id INTEGER,
fk_subject_id INTEGER,
FOREIGN KEY(fk_category_id) REFERENCES category ON DELETE CASCADE ON UPDATE
CASCADE,
FOREIGN KEY(fk_subject_id) REFERENCES subject ON DELETE CASCADE ON UPDATE
CASCADE
);
An identity column isn't automatically a primary key. So your tables category and subjectdon't have any primary keys and thus can't be referenced by a foreign key.
You need to add PRIMARY KEY to the columns of the tables category and subject

What's the right way to use "on cascade delete" on a join table? [duplicate]

I have users, have offers, and a junction table users_offers.
Is there a setup I can carry out with foreign key relations that can ensure that junction data will be automatically deleted when I delete any users or offers?
Declare a referential action: ON DELETE CASCADE, for example:
CREATE TABLE user (
user_id int PRIMARY KEY
);
CREATE TABLE offer (
offer_id int PRIMARY KEY
);
CREATE TABLE user_offer (
user_id int,
offer_id int,
PRIMARY KEY (user_id, offer_id),
FOREIGN KEY (user_id) REFERENCES user (user_id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES offer (offer_id) ON DELETE CASCADE
);
[SQL Fiddle]
Interestingly enough, it seems that specifying referential action in "shorthand" foreign key syntax doesn't work (confirmed under MySQL 5.5.30, 5.6.6 m9). The following gets parsed, but when user is deleted, the corresponding user_offer doesn't get deleted:
CREATE TABLE user_offer (
user_id int REFERENCES user (user_id) ON DELETE CASCADE,
offer_id int REFERENCES offer (offer_id) ON DELETE CASCADE,
PRIMARY KEY (user_id, offer_id)
);
You can specify this within your model creation:
CREATE TABLE users_offers (user_id INT NOT NULL,
offer_id INT NOT NULL,
PRIMARY KEY (user_id, offer_id),
FOREIGN KEY (user_id) REFERENCES users(id)
ON DELETE CASCADE,
FOREIGN KEY (offer_id) REFERENCES offers(id)
ON DELETE CASCADE);
You can see a working example in this Fiddle.

Validating foreign key through tables in postgres

I'm trying to validate a foreign key constraint on my table through another table, but I'm not sure how to go about it, or even the correct nomenclature to google.
I have a User table:
create table User ( id uuid primary key );
Each user can have multiple stores:
create table Store(
id uuid primary key,
user_id uuid foreign key store_user_id_fk references User (id)
);
and each user+store can have products
create table Product(
id uuid primary key,
user_id uuid foreign key product_user_id_fk references User (id),
store_id uuid foreign key product_sotre_id_fk references Store (id),
)
My question is: how can I write a constraint on Product such that any (user_id,store_id) combination also must have a valid entry in the Store table? The case I'm trying to prevent is an entry being added to Product where the store does not also belong to the user.
Is there some way of adding:
CHECK ( store_id == Store.id and user_id == Store.user_id )
To the product table?
Unless I'm misunderstanding your question, I'm pretty sure it would just be:
create table Product(
id uuid primary key,
user_id uuid foreign key product_user_id_fk references User (id),
store_id uuid foreign key product_sotre_id_fk references Store (id),
FOREIGN KEY (user_id, store_id) REFERENCES store(user_id, id)
);
This would indicate that the primary key of store should be (id, user_id) not just id or, at at minimum, it should have a UNIQUE constraint on (id, user_id).

Migrating from Postgresql to Postgres-XL: distributed tables design

I need to scale out our application DB due to the amount of data. It's on PostgreSQL 9.3. So, I've found PostgreSQL-XL and it looks awesome, but I'm having a hard time trying to wrap my head around the limitations for distributed tables. To distribute them by replication (where the whole table is replicated in every datanode) is quite OK, but let's say I have two big related tables that need to be "sharded" along the datanodes:
CREATE TABLE foos
(
id bigserial NOT NULL,
project_id integer NOT NULL,
template_id integer NOT NULL,
batch_id integer,
dataset_id integer NOT NULL,
name text NOT NULL,
CONSTRAINT pk_foos PRIMARY KEY (id),
CONSTRAINT fk_foos_batch_id FOREIGN KEY (batch_id)
REFERENCES batches (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT fk_foos_dataset_id FOREIGN KEY (dataset_id)
REFERENCES datasets (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT fk_foos_project_id FOREIGN KEY (project_id)
REFERENCES projects (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT fk_foos_template_id FOREIGN KEY (template_id)
REFERENCES templates (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT uc_foos UNIQUE (project_id, name)
);
CREATE TABLE foo_childs
(
id bigserial NOT NULL,
foo_id bigint NOT NULL,
template_id integer NOT NULL,
batch_id integer,
ffdata hstore,
CONSTRAINT pk_ff_foos PRIMARY KEY (id),
CONSTRAINT fk_fffoos_batch_id FOREIGN KEY (batch_id)
REFERENCES batches (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT fk_fffoos_foo_id FOREIGN KEY (foo_id)
REFERENCES foos (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT fk_fffoos_template_id FOREIGN KEY (template_id)
REFERENCES templates (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
);
Now Postgres-XL documentation states that:
"(...) in distributed tables, UNIQUE constraints must include the
distribution column of the table"
"(...) the distribution column must be included in PRIMARY KEY"
"(...) column with REFERENCES (FK) should be the distribution column.
(...) PRIMARY KEY must be the distribution column as well."
Their examples are over simplistic and scarse, so can someone please DDL me the two above tables for postgres-XL using DISTRIBUTE BY HASH()?
Or maybe suggest other ways to scale out?
CREATE TABLE foos
( ... ) DISTRIBUTE BY HASH(id);
CREATE TABLE foos_child
( ... ) DISTRIBUTE BY HASH(foo_id);
Now any join on foos.id = foos_child.foo_id can be pushed down and done locally.