Composite primary key for 1-to-many relationship? - sql

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

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.

Table 'tableName' contains a constraint definition with column 'columnName' which is not in the table Java Derby

I am trying to run a SQL script to my database created on Java Derby:
CREATE TABLE USUARIO (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY,
EMAIL VARCHAR(40) NOT NULL UNIQUE,
NOMBRES VARCHAR(20) NOT NULL,
APELLIDOS VARCHAR(20) NOT NULL,
CONTRASEÑA VARCHAR(20) NOT NULL,
CEDULA INTEGER,
TELEFONO INTEGER,
CONSTRAINT ID_USUARIO_PK PRIMARY KEY (ID) -- Primary Key
);
CREATE TABLE ORGANIZACION (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, -- Id autonumérico
NOMBRE VARCHAR(20) NOT NULL,
CONSTRAINT ID_ORGANIZACION_PK PRIMARY KEY (ID),
CONSTRAINT ID_DIRECCION_ORG_FK FOREIGN KEY (DIRECCION_ORG) REFERENCES DIRECCION_ORG (ID),
CONSTRAINT ID_TELEFONO_ORG_FK FOREIGN KEY (TELEFONO_ORG) REFERENCES TELEFONO_ORG (ID)
);
CREATE TABLE TELEFONO_ORG (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, -- Id autonumérico
TELEFONO INTEGER NOT NULL,
CONSTRAINT ID_TELEFONO_ORG_PK PRIMARY KEY (ID)
);
CREATE TABLE DIRECCION_ORG (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, -- Id autonumérico
DIRECCION VARCHAR(300) NOT NULL,
CONSTRAINT ID_DIRECCION_ORG_PK PRIMARY KEY (ID)
);
CREATE TABLE PRODUCTO (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY,
RUTA_IMAGEN VARCHAR(400) NOT NULL,
NOMBRE VARCHAR(20) NOT NULL,
CANTIDAD INTEGER,
PRECIO INTEGER,
COSTO INTEGER,
CONSTRAINT ID_PRODUCTO_PK PRIMARY KEY (ID), -- Primary Key
CONSTRAINT ID_ORGANIZACION_FK FOREIGN KEY (ORGANIZACION) REFERENCES ORGANIZACION (ID)
);
But I am getting this error:
Table ORGANIZACION contains a constraint definition with column
DIRECCION_ORG which is not in the table.
What can be wrong here?
You are making constraints to foreign keys but haven't actually created the columns to contain those keys yet. Make those columns and make the constraints point to them (instead of just using the table's name again). Shown below with -- comments indicating where to add it.
CREATE TABLE USUARIO (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY,
EMAIL VARCHAR(40) NOT NULL UNIQUE,
NOMBRES VARCHAR(20) NOT NULL,
APELLIDOS VARCHAR(20) NOT NULL,
CONTRASEÑA VARCHAR(20) NOT NULL,
CEDULA INTEGER,
TELEFONO INTEGER,
CONSTRAINT ID_USUARIO_PK PRIMARY KEY (ID) -- Primary Key
);
CREATE TABLE ORGANIZACION (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, -- Id autonumérico
NOMBRE VARCHAR(20) NOT NULL,
DIRECCION_ORG_ID INTEGER NOT NULL, -- ADD THIS and change constraint FK name
TELEFONO_ORG_ID INTEGER NOT NULL, -- ADD THIS and change constraint FK name
CONSTRAINT ID_ORGANIZACION_PK PRIMARY KEY (ID),
CONSTRAINT ID_DIRECCION_ORG_FK FOREIGN KEY (DIRECCION_ORG_ID) REFERENCES DIRECCION_ORG (ID),
CONSTRAINT ID_TELEFONO_ORG_FK FOREIGN KEY (TELEFONO_ORG_ID) REFERENCES TELEFONO_ORG (ID)
);
CREATE TABLE TELEFONO_ORG (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, -- Id autonumérico
TELEFONO INTEGER NOT NULL,
CONSTRAINT ID_TELEFONO_ORG_PK PRIMARY KEY (ID)
);
CREATE TABLE DIRECCION_ORG (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY, -- Id autonumérico
DIRECCION VARCHAR(300) NOT NULL,
CONSTRAINT ID_DIRECCION_ORG_PK PRIMARY KEY (ID)
);
CREATE TABLE PRODUCTO (
ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY,
RUTA_IMAGEN VARCHAR(400) NOT NULL,
NOMBRE VARCHAR(20) NOT NULL,
CANTIDAD INTEGER,
PRECIO INTEGER,
COSTO INTEGER,
ORGANIZACION_ID INTEGER NOT NULL, --ADD THIS and change constraint FK name
CONSTRAINT ID_PRODUCTO_PK PRIMARY KEY (ID), -- Primary Key
CONSTRAINT ID_ORGANIZACION_FK FOREIGN KEY (ORGANIZACION_ID) REFERENCES ORGANIZACION (ID)
);
Both the columns DIRECCION_ORG and TELEFONO_ORG are not defined in the table ORGANIZACION
The same problem occurs in the table PRODUCTO where the column ORGANIZACION is not defined
You have an error in your CONSTRAINT clause.
The format of the FOREIGN KEY constraint is:
CONSTRAINT {constraint name} FOREIGN KEY ([This_table_column],...) REFERENCES [Other_table] ([Other_table_column], ...).
Read this: https://db.apache.org/derby/docs/10.1/ref/rrefsqlj13590.html#rrefsqlj13590

Add constraint to compare two attributes of different tables?

Here are my tables. I need to check that the 'program' attribute referenced in StudentsBranch with the table Students and the table Branches is the same. How can I do it?
CREATE TABLE Programmes (
name VARCHAR(200) UNIQUE NOT NULL,
CONSTRAINT pk_Programmes PRIMARY KEY (name)
);
CREATE TABLE Students (
id NUMERIC(10,0) UNIQUE NOT NULL,
program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Students PRIMARY KEY (idnr),
FOREIGN KEY (program) REFERENCES Programmes(name)
);
CREATE TABLE Branches (
name VARCHAR(200) UNIQUE NOT NULL,
program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Branches PRIMARY KEY (name, program),
FOREIGN KEY (program) REFERENCES Programmes(name)
);
CREATE TABLE StudentsBranch (
student NUMERIC(10,0) NOT NULL,
program VARCHAR(200) NOT NULL,
branch VARCHAR(200) NOT NULL,
CONSTRAINT pk_StudentsBranch PRIMARY KEY (student),
/* Below how the foreign keys I think should be */
FOREIGN KEY (student, program) REFERENCES Students(idnr, program),
FOREIGN KEY (branch, program) REFERENCES Branches(name, program)
/* I need to add a constraint to verify that the 'program' in Students
* and the 'program' in Branches are equivalent. How?
*/
);
You can't write that constraint with that existing database model you have now.
The only way I see you could do it, is by changing the primary key of Students to (id, program):
CREATE TABLE Students (
id NUMERIC(10,0) UNIQUE NOT NULL,
program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Students PRIMARY KEY (id, program),
FOREIGN KEY (program) REFERENCES Programmes(name)
);
Then the table StudentsBranch could naturally enforce both FKs with using the single column program, as in:
CREATE TABLE StudentsBranch (
student NUMERIC(10,0) NOT NULL,
program VARCHAR(200) NOT NULL,
branch VARCHAR(200) NOT NULL,
CONSTRAINT pk_StudentsBranch PRIMARY KEY (student),
FOREIGN KEY (student, program) REFERENCES Students (id, program),
FOREIGN KEY (branch, program) REFERENCES Branches (name, program)
);
It is always a good idea to have an numeric column of primary key and have primary key for every table.
Once you have primary key for every table you can referece primary key of a specific table and refere it as foerign key.
CREATE TABLE Programmes (
ID INT,
name VARCHAR(200) UNIQUE NOT NULL,
CONSTRAINT pk_Programmes PRIMARY KEY (ID)
);
CREATE TABLE Students(
id INT,
ProgrammID INT NOT NULL,
CONSTRAINT pk_Students PRIMARY KEY (ID),
FOREIGN KEY (ProgrammID) REFERENCES Programmes(ID)
);
CREATE TABLE Branches (
BranchID INT,
ProgrammID INT NOT NULL,
name VARCHAR(200) UNIQUE NOT NULL,
--program VARCHAR(200) NOT NULL,
CONSTRAINT pk_Branches PRIMARY KEY (BranchID, ProgrammID),
FOREIGN KEY (ProgrammID) REFERENCES Programmes(ID)
);
CREATE TABLE StudentsBranch (
StudentsBranchID INT,
studentID INT NOT NULL,
ProgrammID INT NOT NULL,
BranchID INT NOT NULL,
CONSTRAINT pk_StudentsBranch PRIMARY KEY (StudentsBranchID),
FOREIGN KEY (ProgrammID) REFERENCES Programmes(id),
FOREIGN KEY (studentID) REFERENCES Students(id),
FOREIGN KEY (BranchID, ProgrammID) REFERENCES Branches(BranchID, ProgrammID)
);

foreign key to a table having more than one primary key

so this is my double primary key table
create table order_mattress
(
order_number int,
mattress_id int ,
primary key (order_number,mattress_id)
);
this is my second table
create table mattress
(
mattress_id int IDENTITY(1,1) PRIMARY KEY,
mattress_name varchar(25)
);
i want to mattress_id in the table mattress to be a foreign key to mattress_id in the table order_mattress how is that possible, without having any problem because of the double primary key in the firsttable
I'd change it so that you have 3 tables as opposed to 2:
Simple order table to hold unique order number:
create table orders
(
order_number int IDENTITY(1,1) PRIMARY KEY,
);
Mattress table that hold all unique mattresses:
create table mattress
(
mattress_id int IDENTITY(1,1) PRIMARY KEY,
mattress_name varchar(25)
);
The order mattress table, then links mattresses to orders with foreign keys.
create table order_mattress
(
order_number int FOREIGN KEY REFERENCES orders(order_number),
mattress_id int FOREIGN KEY REFERENCES mattress(mattress_id)
);
You have the direction wrong - if the mattress table describes mattresses, the mattress_order table should have a foreign key to it:
ALTER TABLE order_mattress
ADD FOREIGN KEY (mattress_id)
REFERENCES mattress(mattress_id)
The other direction is indeed impossible as mattress_id is not unique in order_mattress.

Error There are no primary or candidate keys in the referenced table

I'm getting this error when trying to create a table with foreign key:
There are no primary or candidate keys in the referenced table 'TeamToPlayers' that match the referencing column list in the foreign key 'FKey2'.
I don't understand why, there is a primary key in the table TeamToPlayers.
Here are the queries:
create table TeamToPlayers
(TeamName varchar(50) NOT NULL,
PlayerName varchar(50) NOT NULL,
primary key(TeamName,PlayerName),
CONSTRAINT FKey FOREIGN KEY (TeamName) REFERENCES Teams(TeamName)
)
create table Players
(PlayerName varchar(50) NOT NULL,
primary key(PlayerName),
CONSTRAINT FKey2 FOREIGN KEY (PlayerName) REFERENCES TeamToPlayers(PlayerName)
);
Table TeamToPlayers primary key consists of two fields - you must reference both as otherwise it's not a key. I think you may have your key the wrong way round - it should be on TeamToPlayers and referencing Players like so:
create table TeamToPlayers
(
TeamName varchar(50) NOT NULL,
PlayerName varchar(50) NOT NULL,
primary key(TeamName,PlayerName),
CONSTRAINT FKey FOREIGN KEY (TeamName) REFERENCES Teams(TeamName),
CONSTRAINT FKey2 FOREIGN KEY (PlayerName) REFERENCES Players(PlayerName)
)
create table Players
(PlayerName varchar(50) NOT NULL,
primary key(PlayerName),
);