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

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...

Related

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;

MySQL ON DELETE CASCADE not work

i have two table (type innoDb) why when i deleting main table row like
+note(im using arch os so my database server type is maria db)
DELETE FROM buildings
WHERE
building_no = 2;
relation table rows dont delete ???
CREATE TABLE buildings (
building_no INT PRIMARY KEY AUTO_INCREMENT,
building_name VARCHAR(255) NOT NULL,
address VARCHAR(255) NOT NULL
);
CREATE TABLE rooms (
room_no INT PRIMARY KEY AUTO_INCREMENT,
room_name VARCHAR(255) NOT NULL,
building_no INT NOT NULL,
FOREIGN KEY (building_no)
REFERENCES buildings (building_no)
ON DELETE CASCADE
);
This syntax works for me on MySQL database but i can't see issues in your query too
CREATE TABLE `rooms` (
room_no INT PRIMARY KEY AUTO_INCREMENT,
room_name VARCHAR(255) NOT NULL,
building_no INT NOT NULL,
CONSTRAINT `FK_rooms_1` FOREIGN KEY (`building_no`) REFERENCES `buildings`
(`building_no`) ON DELETE CASCADE
) ENGINE=InnoDB;
or add the constraint after table creation
ALTER TABLE `rooms`
ADD CONSTRAINT `FK_rooms_1` FOREIGN KEY (`building_no`) REFERENCES `buildings` (`building_no`) ON DELETE CASCADE ON UPDATE CASCADE;

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?

Errno:150 in MySQL Database

Have an error in my SQL code, but could not understand, where it is. Please, help me to solve that. Here is my code:
CREATE TABLE IF NOT EXISTS Records (
record_id int(11) NOT NULL AUTO_INCREMENT,
record_year year(4) NOT NULL,
record_quarter int(1) NOT NULL,
profit_tax int(11) NOT NULL,
PRIMARY KEY (record_id, record_year, record_quarter),
UNIQUE(record_year, record_quarter)
);
CREATE TABLE IF NOT EXISTS ProductsList (
product_id int(11) NOT NULL AUTO_INCREMENT,
product_name varchar(24) NOT NULL,
PRIMARY KEY (product_id)
);
An error is in that table:
CREATE TABLE IF NOT EXISTS RecordsProducts (
recordproduct_id int(11) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (recordproduct_id),
FOREIGN KEY (record_id) REFERENCES Records (record_id),
FOREIGN KEY (product_id) REFERENCES ProductsList (record_id)
);
referencing column should be INDEX
referencing column should have same data type of referenced column
both referencing, referenced table should be InnoDB
CREATE TABLE IF NOT EXISTS RecordsProducts (
...
...
record_id int NOT NULL, <=== check data type
product_id int NOT NULL,
INDEX(record_id), <===== check INDEXed or not
INDEX(product_id), <====
FOREIGN KEY (record_id) REFERENCES Records (record_id),
FOREIGN KEY (product_id) REFERENCES ProductsList (record_id)
) ENGINE = InnoDB; <=== add 'ENGINE=InnoDB' explicitly

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,