Should Keys be INDICES or compound PRIMARY KEY - mysql

I have a schema with a parent and child table.
A parent record, may have many children (1 to many)
To link these, a third table has the PRIMARY KEY of the parent, and child records.
Should this linking table, have a compound PRIMARY KEY?
Or, should this simply be two FOREIGN KEYS, each with an INDEX()?
CREATE TABLE parent(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE=INNODB;
CREATE TABLE child(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE=INNODB;
So, should the linking table be like..
CREATE TABLE parent_child_link(
parent_id INT NOT NULL,
child_id INT NOT NULL,
INDEX(parent_id),
INDEX(child_id),
FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE,
FOREIGN KEY (child_id) REFERENCES child(id) ON DELETE CASCADE
) ENGINE=INNODB;
Or should this be
CREATE TABLE parent_child_link(
parent_id INT NOT NULL,
child_id INT NOT NULL,
PRIMARY KEY(parent_id, child_id)
) ENGINE=INNODB;

Since its one to many and not many to many, adding a parent_id to the child table is sufficient.

Related

i am trying to create foreign keys but i got error 1822 .. please see my code below

CREATE TABLE employee(
empid int auto_increment primary key,
empfirstname varchar(200) not null,
emplastname varchar(200) not null,
email varchar(200) not null,
officenumber int not null
);
CREATE TABLE customer(
custid int auto_increment primary key,
firstname varchar(200) not null,
lastname varchar(200) not null,
address varchar(200) not null,
contact varchar(200)
);
CREATE TABLE product(
productid int auto_increment primary key,
productdesc varchar(500) not null,
weight int not null,
unit_cost int not null
);
CREATE TABLE productorder(
productid int,
orderid int,
primary key(productid,orderid),
constraint fk3 foreign key (productid) references product(productid),
constraint fk4 foreign key (orderid) references productorder(orderid)
);
CREATE TABLE salesorder(
salesorderid int auto_increment primary key,
empid int not null,
custid int not null,
orderdate date not null,
shippingmethod varchar (200) not null,
constraint a_fk1 foreign key (empid) references employee(empid),
constraint a_fk2 foreign key (custid) references customer(custid)
);
What is this meant to do?:
constraint fk4 foreign key (orderid) references productorder(orderid)
It's not uncommon for a table to have a foreign key back to its own primary key, such as for records which have a parent/child relationship. But that doesn't seem to be the case here.
More to the point of the error though, this isn't referencing the entire primary key for the target table. That key has two fields:
primary key(productid,orderid)
So the DBMS can't create the foreign key because its structure doesn't match the target primary key.
If you want to create that foreign key, it would need to match. Probably something like this:
constraint fk4 foreign key (productid,orderid) references productorder(productid,orderid)
But it doesn't appear that you need that foreign key at all, because it doesn't seem to make sense in your data model. Instead I suspect orderid might need to be autoincrement and just use the productid foreign key. Something like this:
CREATE TABLE productorder(
orderid int auto_increment primary key,
productid int,
constraint fk3 foreign key (productid) references product(productid)
);
(Note that there could be more changes you'd want to make to your data model. This answer doesn't purport to provide you with a complete production-ready data model, just to correct the error. Your data model is likely to change/evolve as you develop your system.)
Its normal,
The foreign key in table **productorder**
is refereing to the table itself:
constraint fk4 foreign key (orderid) references **productorder**(orderid)
In order to achieve the self-referencing constraint on the table productorder, you need to add another column with the same type and make typical referencing.
For instance :
Create table productorder (
productid int,
orderid int,
orderid_parent int,
primary key(productid,orderid),
constraint fk_self foreign key(orderid) references productorder(orderid_parent)
)

How to define Many to Many linking table

I have a schema with a store and product table. A store record, may have many products, and a product may be available to many stores (many to many) To link these, a third table has the PRIMARY KEY of the store, and product records. Should this linking table, have a compound PRIMARY KEY? Or, should this simply be two FOREIGN KEYS, each with an INDEX()?
CREATE TABLE store(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE=INNODB;
CREATE TABLE product(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY(id)
) ENGINE=INNODB;
So, should the linking table be like..
CREATE TABLE store_product_link(
store_id INT NOT NULL,
product_id INT NOT NULL,
INDEX(store_id),
INDEX(product_id),
FOREIGN KEY (store_id) REFERENCES store(id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES product(id) ON DELETE CASCADE
) ENGINE=INNODB;
Or should this be
CREATE TABLE store_product_link(
store_id INT NOT NULL,
product_id INT NOT NULL,
PRIMARY KEY(store_id, product_id)
) ENGINE=INNODB;
Both, it should have a primary key and both foreign keys.
CREATE TABLE store_product_link(store_id INT NOT NULL, product_id INT NOT NULL,
PRIMARY KEY(store_id, product_id),
FOREIGN KEY (store_id) REFERENCES store(id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES product(id) ON DELETE CASCADE) ENGINE=INNODB;

Enforcing cross table uniqueness of records in mysql

I have three tables:
CREATE TABLE A (
id int(11) NOT NULL AUTO_INCREMENT,
adata varchar(255),
PRIMARY KEY (id)
);
CREATE TABLE B (
id int(11) NOT NULL AUTO_INCREMENT,
bdata varchar(255),
a_id int(11) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (a_id) REFERENCES A(id) ON DELETE CASCADE
);
CREATE TABLE C (
id int(11) NOT NULL AUTO_INCREMENT,
cdata varchar(255),
b_id int(11) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (b_id) REFERENCES B(id) ON DELETE CASCADE
);
Elements of C (associated with B's) must be unique only for a given A. I.e., the combination of (cdata and b_id.a_id) must be unique.
I realize that I could add another column (pointing to A) to the C table and create a unique key. Is there any way to enforce uniqueness without adding another column to C?

Confusing cannot add foreign key constraint error

Ok, maybe it's late and I'm being stupid, but I can't seem to figure out why I'm getting a Cannot add Foreign Key Constraint error for the following query
DROP TABLE IF EXISTS People_Lordships;
CREATE TABLE People_Lordships
(
Id INT PRIMARY KEY AUTO_INCREMENT,
PersonId INT NOT NULL,
LordshipId INT NOT NULL,
AssumedDate Date,
AbdicatedDate Date
);
DROP TABLE IF EXISTS People_Lordships_Current;
CREATE TABLE People_Lordships_Current
(
Id INT PRIMARY KEY AUTO_INCREMENT,
People_LordshipsId INT NOT NULL,
LordShipId INT NOT NULL,
CONSTRAINT Fk_People_Lordships_Current_People_LordshipsId_LordshipId
FOREIGN KEY (`LordshipId`,`People_LordshipsId`)
REFERENCES People_Lordships (`LordshipId`,`Id`)
ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT UQ_People_Lordships_Current_LordshipId
UNIQUE KEY (`LordshipId`)
);
And yes, it is a database about noble titles... it's a long story
There is no column LordshipId in table People_Lordships.
Your foreign key definition attempts to reference a column that doesn't exist.
REFERENCES People_Lordships (`LordshipId`,`Id`)
^^^^^^^^^^^^
Figured this one out.
It turns out MySQL cannot add a foreign key constraint against a column that is not the first column in an index.
The following will work
DROP TABLE IF EXISTS People_Lordships;
CREATE TABLE People_Lordships
(
Id INT PRIMARY KEY AUTO_INCREMENT,
PersonId INT NOT NULL,
LordshipId INT NOT NULL,
AssumedDate Date,
AbdicatedDate Date,
INDEX Idx_LordshipId (LordshipId)
);
DROP TABLE IF EXISTS People_Lordships_Current;
CREATE TABLE People_Lordships_Current
(
Id INT PRIMARY KEY AUTO_INCREMENT,
People_LordshipsId INT NOT NULL,
LordShipId INT NOT NULL,
CONSTRAINT Fk_People_Lordships_Current_People_LordshipsId_LordshipId
FOREIGN KEY (`LordshipId`,`People_LordshipsId`)
REFERENCES People_Lordships (`LordshipId`,`Id`)
ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT UQ_People_Lordships_Current_LordshipId
UNIQUE KEY (`LordshipId`)
);

Foreign key constraints seem ignored by mysql

I am just making a foreign key reference of parent table in a child table. When I try to delete the row from the parent table whose reference is there in child table, surprisingly it allows me to delete it. I have tried to create child table explicitly by writing on delete restrict and also without it, but to no help. Any ideas why this is happening? Below is the code I am using while creating the tables.
CREATE TABLE region
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
);
CREATE TABLE aggregator
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
);
CREATE TABLE gateway
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL,
region_id int ,
aggregator_id int ,
is_public boolean DEFAULT 0 NOT NULL,
FOREIGN KEY (region_id) REFERENCES region(id),
FOREIGN KEY (aggregator_id) REFERENCES aggregator(id)
);
Both parent and child table need to be INNODB tables.
Try:
CREATE TABLE region
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
) ENGINE=INNODB;
CREATE TABLE aggregator
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL
) ENGINE=INNODB;
CREATE TABLE gateway
(
id int PRIMARY KEY AUTO_INCREMENT,
name varchar(50) NOT NULL,
region_id int ,
aggregator_id int ,
is_public boolean DEFAULT 0 NOT NULL,
FOREIGN KEY (region_id) REFERENCES region(id),
FOREIGN KEY (aggregator_id) REFERENCES aggregator(id)
) ENGINE=INNODB;
Do mean to say that if you delete parent table and child table deletes automatic? If yes then once go through cascading rules.