Add a reference to a postgrest table - sql

I want to alter the artist_label to be label_id BIGINT NOT NULL REFERENCES label(id) like how it is in the album_label table.
CREATE TABLE label (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
parent_label_id BIGINT REFERENCES label(id)
);
CREATE TABLE album_label (
id BIGSERIAL PRIMARY KEY,
album_id TEXT NOT NULL UNIQUE,
label_id BIGINT NOT NULL REFERENCES label(id)
);
CREATE INDEX album_label_idx ON album_label(label_id);
CREATE INDEX album_uid_idx ON album_label(id)
CREATE TABLE artist_label (
artist_id VARCHAR(60) NOT NULL,
label_id BIGINT NOT NULL,
PRIMARY KEY (artist_id, label_id)
);
CREATE INDEX artist_label_idx ON artist_label(label_id);

If you haven't created the tables yet, you could modify the creation script and add that clause.
If you're asking how to modify the table after its creation, you can use an alter table statement:
ALTER TABLE artist_label
ADD CONSTRAINT artist_label_fk FOREIGN KEY (label_id) REFERENCES label(id)
SQLFiddle Example

Related

How to add foreign key that points to one of 2 tables with Postgres?

I want to add a foreign key that is check record_id of activity exists in one of the record or personal_record tables. Is it possible to do with Postgres?
CREATE TABLE record
(
id BIGSERIAL PRIMARY KEY
);
CREATE TABLE personal_record
(
id BIGSERIAL PRIMARY KEY
);
CREATE TABLE activity
(
id BIGSERIAL PRIMARY KEY,
record_id BIGINT NOT NULL,
CONSTRAINT record_fk FOREIGN KEY (record_id) REFERENCES record (id)
);
As stated, this is not possible. One possibility is generated columns and nullable references:
CREATE TABLE activity (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
private_record_id BIGINT,
private_personal_record_id BIGINT,
record_id BIGINT GENERATED ALWAYS AS (COLAESCE(private_record_id, private_personal_record_id)),
CHECK( (private_record_id IS NOT NULL AND private_personal_record_id IS NULL) OR
(private_record_id IS NULL AND private_personal_record_id IS NOT NULL)
),
CONSTRAINT fk_activity_record_id FOREIGN KEY (private_record_id) REFERENCES record(id),
CONSTRAINT fk_activity_record_id FOREIGN KEY (private_personal_record_id) REFERENCES personal_record(id),
);
You might also want to look into inheritance.

ERROR: No unique constraint matching when having FK

I have three tables that are linked together
My script:
-- Ticket --
CREATE TABLE public.ticket (
id bigint NOT NULL,
libelle character varying(255) NOT NULL,
description character varying(255) NOT NULL,
status character varying(255) NOT NULL,
date_creation timestamp NOT NULL,
date_modification timestamp NOT NULL,
user_createur_id bigint,
referent_realisateur_id bigint,
CONSTRAINT pk_ticket PRIMARY KEY (id)
);
-- Ticket_Avance TABLE --
CREATE TABLE public.ticket_avance (
id bigint NOT NULL,
date_livraison_souhaite timestamp NOT NULL,
date_engagement_livraison timestamp NOT NULL,
referent_demandeur_id bigint
);
ALTER TABLE public.ticket_avance ADD CONSTRAINT "fk_ticket_ticketAvance" FOREIGN KEY (id)
REFERENCES public.ticket (id) MATCH SIMPLE
ON DELETE NO ACTION ON UPDATE NO ACTION;
-- Demande_Travaux TABLE --
DROP TABLE IF EXISTS public.demande_travaux CASCADE;
CREATE TABLE public.demande_travaux (
id bigint NOT NULL,
contrat_id bigint
);
ALTER TABLE public.demande_travaux ADD CONSTRAINT "fk_ticketAvance_DDT" FOREIGN KEY (id)
REFERENCES public.ticket_avance (id) MATCH FULL
ON DELETE NO ACTION ON UPDATE NO ACTION;
I have this error on the demand_travaux creation
SQL Error [42830]: ERROR: there is no unique constraint matching given keys for referenced table "ticket_avance"
ERROR: there is no unique constraint matching given keys for referenced table "ticket_avance"
ERROR: there is no unique constraint matching given keys for referenced table "ticket_avance"
You have forgotten to declare column ID in table ticket_avance as primary key.
Please use the following SQL:
-- Ticket_Avance TABLE --
CREATE TABLE public.ticket_avance (
id bigint NOT NULL,
date_livraison_souhaite timestamp NOT NULL,
date_engagement_livraison timestamp NOT NULL,
referent_demandeur_id bigint,
CONSTRAINT pk_avance PRIMARY KEY (id) --- add this
);
you need add constraint in Ticket_Avance table because you provide reference this id to demande_travaux
-- Ticket_Avance TABLE --
CREATE TABLE ticket_avance (
id bigint NOT NULL,
date_livraison_souhaite timestamp NOT NULL,
date_engagement_livraison timestamp NOT NULL,
referent_demandeur_id bigint,
CONSTRAINT pk_ticket_avance PRIMARY KEY (id) //constraint that you need
);
ALTER TABLE demande_travaux ADD CONSTRAINT "fk_ticketAvance_DDT" FOREIGN KEY (id)
REFERENCES ticket_avance (id) MATCH FULL
ON DELETE NO ACTION ON UPDATE NO ACTION;
here is the demo link of your full query
A foreign key constraint has to target a primary key or unique constraint. The database has to be able to identify a single row in the "parent" table.
You could add primary key constraints:
ALTER TABLE public.ticket_avance ADD PRIMARY KEY (id);
In addition, you should have an index on the column on which the foreign key is defined, particularly if you plan to delete parent rows. With the primary key above, you have such an index on id, but you also should have one on demande_travaux.
The simplest way is to define id as primary key there too:
ALTER TABLE public.demande_travaux ADD PRIMARY KEY (id);

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.

Composite primary key for 1-to-many relationship?

Well, I was always doing it like this:
create table language (
id bigserial primary key,
code varchar(10) not null
);
create table entity (
id bigserial primary key
);
create table entity_description (
id bigserial primary key,
language_id bigint not null,
constraint fk__entity_description__language
foreign key language_id
references language(id),
entity_id bigint not null,
constraint fk__entity_description__entity
foreign key entity_id
references entity(id),
name varchar(20) not null
);
but I wonder.. why wouldn't I do it like this:
create table language (
id bigserial primary key,
code varchar(10) not null
);
create table entity (
id bigserial primary key
);
create table entity_description (
language_id bigint not null,
constraint fk__entity_description__language
foreign key language_id
references language(id),
entity_id bigint not null,
constraint fk__entity_description__entity
foreign key entity_id
references entity(id),
primary key (language_id, entity_id),
name varchar(20) not null
);
My questions are
Is there anything that speaks against the composite primary key in the second example?
Are there any benefits?
Are, in the second example, (language_id, entity_id), language_id and entity_id indexed separately for table entity_description? If I fetch for .. WHERE entity_description.id = x is this slower than fetching for .. WHERE (entity_description.language_id, entity_description.entity_id) = (x,y)?

How can I get around this foreign key constraint having to have a unique name?

I'm not sure why these have to be unique, but from reading the MySQL forums it appears that they do. However, I think it has something more to do with the INDEX name. I have two tables that have foreign key constraints referencing the same primary key on a third table. If it helps, I'm using MySQL workbench to design the schema.
I usually name my foreign key on each table the same name as the primary key it references. I guess this isn't possible. It will create the first table with the foreign key constraint, but when it tries to create the second table it throws an error. Here is the second table it throws the error on:
CREATE TABLE IF NOT EXISTS `joe`.`products_to_categories` (
`product_to_category_id` INT NOT NULL AUTO_INCREMENT ,
`category_id` INT NOT NULL ,
`product_id` INT NOT NULL ,
PRIMARY KEY (`product_to_category_id`) ,
INDEX `category_id` (`category_id` ASC) ,
INDEX `product_id` (`product_id` ASC) ,
CONSTRAINT `category_id`
FOREIGN KEY (`category_id` )
REFERENCES `joe`.`categories` (`category_id` )
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `product_id`
FOREIGN KEY (`product_id` )
REFERENCES `joe`.`products` (`product_id` )
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
I want the foreign key names to be the same as the primary key in both of the other tables. What should I remove here so that I can use these names. What is the best practice here.
It is not possible because you would have a conflict in the filename for the file that is used for the index IIRC. I probably would name the key < tablename >_< column_name > or something like that.
You are creating an index (constraint) by the name of product_id via:
INDEX product_id
Then you are going and creating another constraint (for the foreign key) with the same name:
CONSTRAINT product_id
What you need to do is allow the server to provide a default, unique constraint name by removing the
CONSTRAINT product_id
See this URL: http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
"If the CONSTRAINT symbol clause is given, the symbol value must be unique in the database. If the clause is not given, InnoDB creates the name automatically."
In PostgreSQL, the default for naming indexes is to append "_pkey" and "_fkey" to the name of the primary and foreign key, respectively. So your case would look like:
INDEX `product_id_fkey` (`product_id` ASC) ,
UPDATE: I just tried this and it worked. See if that's what you had in mind.
use test;
create table if not exists test.product
(
product_id int not null auto_increment,
name varchar(80) not null,
primary key(product_id)
);
create table if not exists test.category
(
category_id int not null auto_increment,
name varchar(80) not null,
primary key(category_id)
);
create table if not exists test.product_category
(
product_id int,
category_id int,
primary key(product_id, category_id),
constraint product_id_fkey
foreign key(product_id) references product(product_id)
on delete cascade
on update no action,
constraint category_id_fkey
foreign key(category_id) references category(category_id)
on delete cascade
on update no action
);
insert into test.product(name) values('teddy bear');
insert into test.category(name) values('toy');
insert into test.product_category
select p.product_id, c.category_id from product as p, category as c
where p.name = 'teddy bear' and c.name = 'toy';