How to define Many to Many linking table - mysql

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;

Related

Should Keys be INDICES or compound PRIMARY KEY

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.

Cannot add foreign key constraint MySQL Workbench

I'm getting "Error Code: 1215. Cannot add foreign key constraint" when trying to create the "orders" table.
credit_cards table:
CREATE TABLE credit_cards (
customer VARCHAR(30),
card_no CHAR(16),
PRIMARY KEY (customer, card_no),
FOREIGN KEY (customer) REFERENCES customers(username));
orders table:
CREATE TABLE orders (
order_no INT AUTO_INCREMENT,
customer VARCHAR(30) NOT NULL,
date_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
credit_card CHAR(16) NOT NULL,
PRIMARY KEY (order_no),
FOREIGN KEY (customer)
REFERENCES customers (username),
FOREIGN KEY (credit_card)
REFERENCES credit_cards (card_no));
The report from SHOW ENGINE INNODB STATUS says that the problem is FOREIGN KEY (credit_card) REFERENCES credit_cards(card_no))
I've read a bunch of resolved questions and still can't figure it out. I'm using MySQL Workbench. Thanks.
You need to reference all the keys in a primary key (or unique key) relationship. I would recommend:
CREATE TABLE credit_cards (
credit_card_id int auto_increment primary key,
customer VARCHAR(30),
card_no CHAR(16),
UNIQUE KEY (customer, card_no),
FOREIGN KEY (customer) REFERENCES customers(username));
orders table:
CREATE TABLE orders (
order_no INT AUTO_INCREMENT,
customer VARCHAR(30) NOT NULL,
date_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
credit_card_id int NOT NULL,
PRIMARY KEY (order_no),
FOREIGN KEY (customer)
REFERENCES customers (username),
FOREIGN KEY (credit_card_id)
REFERENCES credit_cards (credit_card_id));

can't add foreign key constraint in mysql

create table buys (
user_id INT(11) not null,
software_id INT(11) not null,
associated_id INT(11) not null,
primary key (associated_id),
foreign key (software_id) references software,
foreign key (user_id) references users,
foreign key (associated_id) references associated);
I have a ternary relationship associated table having total participation and a key constraint but cannot add foreign key constraints
Check the following query:
CREATE TABLE products(
prd_id int not null auto_increment primary key,
cat_id int not null,
FOREIGN KEY fk_cat(cat_id)
REFERENCES categories(cat_id)
)ENGINE=InnoDB;
In your case:
foreign key (software_id) references software -> here column name is missing in software table

MySQL - Can't create table (errno: 150) - Foreign key constraints

I want to create these 3 tables in my MySQL database:
CREATE TABLE categories (
category_id SMALLINT NOT NULL AUTO_INCREMENT,
category VARCHAR(255) NOT NULL UNIQUE,
description TINYTEXT NOT NULL,
PRIMARY KEY (category_id)
);
CREATE TABLE product (
product_id SMALLINT NOT NULL AUTO_INCREMENT,
product VARCHAR(255) NOT NULL UNIQUE,
description TINYTEXT NOT NULL,
price DECIMAL(6,2) NOT NULL,
PRIMARY KEY (product_id)
);
CREATE TABLE categories_products (
category_id SMALLINT NOT NULL,
product_id SMALLINT NOT NULL,
PRIMARY KEY (category_id, product_id),
FOREIGN KEY (category_id) REFERENCES categories (category_id)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id)
ON DELETE CASCADE ON UPDATE CASCADE
);
The problem is with the last table. I get an error:
1005 - Can't create table 'test1.categories_products' (errno:
150)
But when i try to create it without the constraints it works.
CREATE TABLE categories_products (
category_id SMALLINT NOT NULL,
product_id SMALLINT NOT NULL,
PRIMARY KEY (category_id, product_id)
);
I need the constraints in case a product or a category is removed. What am i doing wrong?
There seems to be a typo
CREATE TABLE product
(singular)
and then referencing
FOREIGN KEY (product_id) REFERENCES products (product_id)
(plural).
CREATE TABLE categories (
category_id SMALLINT NOT NULL AUTO_INCREMENT,
category VARCHAR(255) NOT NULL UNIQUE,
description TINYTEXT NOT NULL,
PRIMARY KEY (category_id)
);
CREATE TABLE products (
product_id SMALLINT NOT NULL AUTO_INCREMENT,
product VARCHAR(255) NOT NULL UNIQUE,
description TINYTEXT NOT NULL,
price DECIMAL(6,2) NOT NULL,
PRIMARY KEY (product_id)
);
CREATE TABLE categories_products (
category_id SMALLINT NOT NULL,
product_id SMALLINT NOT NULL,
PRIMARY KEY (category_id, product_id),
FOREIGN KEY (category_id) REFERENCES categories (category_id)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (product_id) REFERENCES products (product_id)
ON DELETE CASCADE ON UPDATE CASCADE
);
You created "product" but referenced "products".
By the way, you should create an ID column and use this one as primary key in "categories_products" and add a second (unique) index on both columns. This is best practice and INNODB does internally create an ID column anyway so...

Can't figure out what's wrong with foreign key constraint statement

This is the error message from show engine innodb status; when I try to create the table:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
110628 16:56:07 Error in foreign key constraint of table test/menu_items:
foreign key(id_menu)
references menus(id)
on update cascade
on delete cascade,
foreign key(id_item)
references items(id)
on update cascade
on delete cascade,
primary key(id_menu, id_item)
) engine=InnoDB:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
These are the relevant SQL statements:
create table if not exists menus (
id mediumint unsigned not null auto_increment,
id_restaurant mediumint unsigned not null,
name varchar(50) not null,
description varchar(255) default null,
foreign key(id_restaurant)
references restaurants(id)
on update cascade
on delete cascade,
primary key(id)
) engine=InnoDB;
create table if not exists items (
id mediumint unsigned not null auto_increment,
id_restaurant mediumint unsigned not null,
name varchar(50),
description text,
type enum('appetizer','salad','soup','entree','dessert','drink','other'),
price decimal(4,2),
foreign key(id_restaurant)
references restaurants(id)
on update cascade
on delete cascade,
primary key(id)
) engine=InnoDB;
create table if not exists order_items (
id_order bigint unsigned not null,
id_item mediumint unsigned not null,
item_name varchar(50),
item_description text,
item_price decimal(4,2),
notes varchar(1024),
quantity smallint unsigned,
foreign key(id_order)
references orders(id)
on update cascade
on delete cascade,
foreign key(id_item)
references items(id)
on update cascade
on delete cascade,
primary key(id_order, id_item)
) engine=InnoDB;
Removing menu_items.id_menu and corresponding foreign key / primary key allows the SQL statements to be parsed properly.
Why can't I make a foreign key reference to menus(id) from menu_items?
You've got a mismatch of datatypes:
create table order_items (
id_order bigint unsigned not null, -- BIGINT
create table items (
id mediumint unsigned not null auto_increment, -- MEDIUMINT
but order_items.id_order references items.id, so they should be the same.
Try changing order_items id_order to medium int:
order_items (
id_order mediumint unsigned not null,