Declare Foreign key in MySQL - mysql

I have these database
=== Invoices ===
id
status
description
=== Invoice Items ===
id
invoice_id (FK)
item_name
description
To make this table I have made this MySQL command
CREATE TABLE IF NOT EXISTS `nt_invoices` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`status` varchar(45) NOT NULL DEFAULT '',
`description` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;
CREATE TABLE IF NOT EXISTS `nt_invoice_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`invoice_id` int(11) NOT NULL,
`item_name` varchar(45) NOT NULL,
`description` text NOT NULL,
PRIMARY KEY (`id`),
KEY `invoice_id` (`invoice_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ;
My problem is that I want to declare a foreign key in the invoice_items table and to make the invoice_id the foreign key of invoices table id. So how to write that command? Any help and suggestions will be highly appreciated.

MyISAM does not support foreign keys. You need to use InnoDB (which is a better choice in all aspects anyway). Then it's just like in any other SQL dialect:
`invoice_id` int(11) NOT NULL references nt_invoices(id),
P.S. Also, always use utf8 encoding everywhere. It will bite you in the ass if you don't.

You should have innodb engine type for using foreign keys.
CREATE TABLE IF NOT EXISTS `nt_invoice_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`invoice_id` int(11) NOT NULL references nt_invoices(id)
`item_name` varchar(45) NOT NULL,
`description` text NOT NULL,
PRIMARY KEY (`id`),
KEY `invoice_id` (`invoice_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
OR if you want to use cascaded update delete:
CREATE TABLE IF NOT EXISTS `nt_invoice_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`invoice_id` int(11) NOT NULL,
`item_name` varchar(45) NOT NULL,
`description` text NOT NULL,
PRIMARY KEY (`id`),
KEY `invoice_id` (`invoice_id`),
FOREIGN KEY (invoice_id) REFERENCES nt_invoices(id)
ON DELETE CASCADE
ON UPDATE CASCADE,
) ENGINE=INNODB DEFAULT CHARSET=utf8;

You may also use ALTER command to declare FOREIGN KEY as follows:
Alter table table_name add foreign key(column_name)
references other_table_name(column);

Related

Cannot add foreign key constraint in phpmyadmin - mysql

I have a table called teachers. I cannot use the id from teachers to create a composite table in slot table with the following query.
CREATE TABLE `teachers` (
`id` bigint(20) UNSIGNED NOT NULL,
`first_name` varchar(255) NOT NULL,
`last_name` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE `teachers`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `teachers_email_unique` (`email`);
to create slot table
CREATE TABLE `slot` (
`teacher_id` bigint(20) NOT NULL,
`is_confirmed` tinyint(1) NOT NULL,
PRIMARY kEY (`teacher_id`),
foreign key (`teacher_id`) references `teachers`(`id`) on delete CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Data type of the referencing and referenced fields, should be exactly the same while defining a Foreign Key constraint. In your teachers table, id is BIGINT UNSIGNED, while in your slot table, it is BIGINT only. Add UNSIGNED clause as well:
CREATE TABLE `slot` (
`teacher_id` bigint(20) UNSIGNED NOT NULL,
`is_confirmed` tinyint(1) NOT NULL,
PRIMARY kEY (`teacher_id`),
foreign key (`teacher_id`) references `teachers`(`id`) on delete CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

MySQL UNIQUE KEY and FOREIGN KEY same column not getting created

I have following tables/CREATE sintaxis:
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parentId` int(10) unsigned DEFAULT NULL,
`fullName` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`alias` varchar(35) COLLATE utf8_unicode_ci DEFAULT NULL,
`username` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_parentId_fullName_alias` (`parentId`,`fullName`,`alias`),
KEY `fk_users_parentId` (`parentId`),
CONSTRAINT `fk_users_parentId` FOREIGN KEY (`parentId`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `userSettings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`userId` int(11) unsigned NOT NULL,
`settingsArray` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_userId` (`userId`),
KEY `fk_userSettings_userId` (`userId`),
CONSTRAINT `fk_userSettings_userId` FOREIGN KEY (`userId`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
im trying to create one table with user data and another one with the user settings, when i create the userSettings table it doesnt create the foreign key, is there something wrong with the create sintaxis? It is related with creating two indexes for same column?
Here what i get after creating the userSettings table:
CREATE TABLE `userSettings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`userId` int(11) unsigned NOT NULL,
`settingsArray` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_userId` (`userId`),
KEY `fk_userSettings_userId` (`userId`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
As you discovered, MyISAM doesn't support foreign keys. Both users and userSettings must be InnoDB.
[I'm] just curious if having a UNIQUE_KEY and FOREIGN_KEY in same column is a good practice
This means the userSettings table can have at most one row for each userId. I guess you need only one row per userId because you store an "array" of settings encoded somehow in your settingsArray TEXT column. This is not a good practice.
You should either store each setting in its own column:
CREATE TABLE `userSettings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`userId` int(11) unsigned NOT NULL,
`isAdmin` bool NOT NULL,
`timezone` varchar(10) NOT NULL,
`theme` varchar(10) NOT NULL,
...other settings...
PRIMARY KEY (`id`),
UNIQUE KEY `uk_userId` (`userId`),
KEY `fk_userSettings_userId` (`userId`)
)
Or else store multiple rows per userId, with one setting name and value per row.
CREATE TABLE `userSettings` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`userId` int(11) unsigned NOT NULL,
`setting` varchar(20) NOT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_userId` (`userId`,`setting`),
KEY `fk_userSettings_userId` (`userId`)
)
It's also puzzling why you need an id column for the primary key, if the userId is already NOT NULL and UNIQUE, and that's probably the key you'll use to look up rows anyway. You can make the userId the PRIMARY KEY as well (or userId, setting in the second example), and omit the id column.
Just realized for the table users the ENGINE was InnoDB and for the userSettings table ENGINE was MyISAM, changed that and worked, im just curious if having a UNIQUE_KEY and FOREIGN_KEY in same column is a good practice

Should I use one mapping table for multiple data-type tables, or create different mapping tables for each data-type?

At the moment I have one huge tag table and I use mapping table to map tags with another mapping table to map with data table. The reason I added another mapping-to-data table is that I have multiple different data tables.
There are two data tables:
CREATE TABLE IF NOT EXISTS `cars_list` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) default NULL,
`description` varchar(255) default NULL,
`photo` varchar(45) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `website_list` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) default NULL,
`description` varchar(255) default NULL,
`url` varchar(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Both of them I use in my search fields, and they should be linked to one TAG list table
There's tag table:
CREATE TABLE IF NOT EXISTS `tags` (
`tag_id` int(11) NOT NULL auto_increment,
`tag` varchar(255) default NULL,
PRIMARY KEY (`tag_id`),
UNIQUE KEY `tag` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And what I do - I use two more tables to map data tables with tags:
Two mapping tables:
CREATE TABLE IF NOT EXISTS `tags_map_type` (
`tmtid` int(11) NOT NULL auto_increment,
`type` enum('cars_list','website_list') NOT NULL,
`type_id` int(11) NOT NULL,
PRIMARY KEY (`tmtid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `tags_map` (
`tmid` int(11) NOT NULL auto_increment,
`map_type_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`tmid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `tags_map`
ADD CONSTRAINT `tag_id` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`tag_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `map_type_id` FOREIGN KEY (`map_type_id`) REFERENCES `tags_map_type` (`tmtid`) ON DELETE CASCADE ON UPDATE CASCADE;
And table tags_map_type then links either to cars_list or to website_list
QUESTION:
How can I make a foreign key to link tags_map_type to one of the list tables?
Or should I use another mapping table for each cars_list, website_list, some_other_list table?
Which way is correct and best to use?

Designing E-commerce database and mysql error

I am trying to make an e-commerce site from scratch. Currently I am trying to make the database.
These are the core tables that the database will have:
Customer: which will have email, username, password....
Customers_Session: Stores information about customer session in hash
Group: basically tells what permissions a customer will have
Category: the category type of a product
Product: information about a product such as name, and description...
Product_Price: Price info on products. This will store the different prices put for each product at various times.
Product_Variation: information about product images, and various colors or styles of a product.
Customer_Orders: What products a customer has ordered.
Customer_Reviews: Reviews made by customers on a product.
Reviewed Products: This table is created based on many to many relationship between the Product table and the Review Table.
Ordered products: This table is created based on the many to many relationship between the Product and the Orders Table.
Based on the above, I have come up with the sql code below:
--
-- Table structure for table `users`
--
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`username` varchar(30) NOT NULL,
`password` varchar(64) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`address` varchar(320) NOT NULL,
`zip` mediumint(5) NOT NULL,
`salt` varchar(40) NOT NULL,
`joined` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`group` tinyint(1) NOT NULL,
`dob` date NOT NULL,
`pic_url` varchar(225) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
--
-- Table structure for table `groups`
--
CREATE TABLE IF NOT EXISTS `groups` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`permissions` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
-- This is for category table
--
CREATE TABLE IF NOT EXISTS `category`(
`category_id` tinyint(3) NOT NULL AUTO_INCREMENT,
`category_type` varchar(100) NOT NULL,
`category_description` varchar(160) NOT NULL,
PRIMARY KEY (`category_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
--
-- This is for product table
--
CREATE TABLE IF NOT EXISTS `products`(
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`product_name` varchar(100) NOT NULL UNIQUE,
`product_description` varchar(160) NOT NULL,
`quantity` int(5) NOT NULL,
`product_code` varchar(4) NOT NULL,
`keywords` varchar(70) NOT NULL,
`category_id` tinyint(3),
PRIMARY KEY (`product_id`),
INDEX (`category_id`),
CONSTRAINT FOREIGN KEY (`category_id`) REFERENCES category(`category_id`) ON DELETE SET NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
--
--
-- Table structure for table `bookings`
--
CREATE TABLE IF NOT EXISTS `bookings` (
`bookings_id` int(11) NOT NULL AUTO_INCREMENT,
`party_type` varchar(50) NOT NULL,
`location` varchar(100) NOT NULL,
`day` varchar(10) NOT NULL,
`time` smallint(6) NOT NULL,
`people_count` smallint(6) NOT NULL,
`booking_name` varchar(50) NOT NULL,
`booking_email` varchar(50) NOT NULL,
PRIMARY KEY (`bookings_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This is for the bookings' AUTO_INCREMENT=1 ;
--
-- Dumping data for table `groups`
--
INSERT INTO `groups` (`id`, `name`, `permissions`) VALUES
(1, 'Administrator', '{"admin":1}'),
(2, 'Users', '{"users":2}');
--
-- Table Structure for Reviews
--
CREATE TABLE IF NOT EXISTS `customer_reviews`(
`reviews_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11),
`rating` int(5) NOT NULL,
`comment` varchar(160) NOT NULL,
PRIMARY KEY(`reviews_id`),
INDEX (`user_id`),
CONSTRAINT FOREIGN KEY(`user_id`) REFERENCES users(`user_id`) ON DELETE SET NULL
)ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
--
-- Table structure for reviewed products This is a many relationshi btw reviews table and product
--
CREATE TABLE IF NOT EXISTS `reviewed_products`(
`product_id` int(11),
`reviews_id`int(11),
PRIMARY KEY(`product_id`,`reviews_id`),
CONSTRAINT FOREIGN KEY(`product_id`) REFERENCES products(`product_id`) ON DELETE SET NULL,
CONSTRAINT FOREIGN KEY(`reviews_id`) REFERENCES customer_reviews(`reviews_id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This is for many to many cardinality btw reviews and products' AUTO_INCREMENT=1 ;
--
--
-- Table structure for table `orders`
--
CREATE TABLE IF NOT EXISTS `customer_orders` (
`order_id` int(11) NOT NULL AUTO_INCREMENT,
`order_time` int(11) NOT NULL,
`amount` int(5),
`confirmation_number` int(,
`user_id` int(11),
`product_id` int(11),
PRIMARY KEY (`order_id`),
INDEX (`user_id`),
CONSTRAINT FOREIGN KEY (`user_id`) REFERENCES users(`user_id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
/* We need a new table since the customer_order and product is in a many to many relationship */
--
--
-- Table structure for table `curtomer_order_product`
--
CREATE TABLE IF NOT EXISTS `ordered_product`(
`product_id` int(11),
`order_id` int(11),
`quantity` smallint(5),
PRIMARY KEY(`product_id`,`order_id`),
INDEX (`product_id`,`order_id`),
CONSTRAINT FOREIGN KEY (`order_id`) REFERENCES customer_orders(`order_id`) ON DELETE RESTRICT,
CONSTRAINT FOREIGN KEY (`product_id`) REFERENCES products(`product_id`) ON DELETE RESTRICT
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
-- This is for price table
--
CREATE TABLE IF NOT EXISTS `product_price`(
`price_id` int(11) NOT NULL AUTO_INCREMENT,
`price` decimal(6,2) NOT NULL,
`product_id` int(11) NOT NULL,
PRIMARY KEY (`price_id`),
INDEX (`product_id`),
CONSTRAINT FOREIGN KEY (`product_id`) REFERENCES products(`product_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
--
-- Table structure for table `product_variations`
--
CREATE TABLE IF NOT EXISTS `product_variations`(
`variations_id` int(11) NOT NULL AUTO_INCREMENT,
`color_name` varchar(10) NOT NULL,
`color_value` char(6) NOT NULL,
`product_id` int(11),
`picture1` varchar(100) NOT NULL,
`picture2` varchar(100) NOT NULL,
`picture3` varchar(100) NOT NULL,
PRIMARY KEY (`variations_id`),
INDEX (`product_id`),
CONSTRAINT FOREIGN KEY (`product_id`) REFERENCES products(`product_id`) ON DELETE RESTRICT
)ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
--
-- Table structure for table `users_session`
--
CREATE TABLE IF NOT EXISTS `users_session` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`hash` varchar(64) NOT NULL,
PRIMARY KEY (`id`),
INDEX (`user_id`),
CONSTRAINT FOREIGN KEY(`user_id`) REFERENCES users(`user_id`) ON DELETE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
The problem is that when I try to run the above code in PHPmyadmin, I get an error stating "Cannot add foreign key constraint". This starts to happen when creating the customer_Reviews table and any other subsequent tables that require foreign keys.
My questions are:
1. Would you recommend designing the database this way.
2. Why am I getting the "Cannot add foreign key constraint" error?
Thanks.
For a full quality review of your database design, you might try the Code Review sister site. At a glance, I don't see any glaring issues with your database design or your SQL.
The foreign key constraint is failing because you have misnamed the column in question.
CONSTRAINT FOREIGN KEY(`user_id`) REFERENCES users(`user_id`)
should be:
CONSTRAINT FOREIGN KEY(`user_id`) REFERENCES users(`id`)

how to get autoincrement ID of one table and insert in another table

I have a mysql table whose description is given below
Create Table
CREATE TABLE `question` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`category` varchar(255) DEFAULT NULL,
`is_deleted` bit(1) NOT NULL,
`question` varchar(255) DEFAULT NULL,
`version` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8
I have another table
Create Table
CREATE TABLE `parent_question` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`is_deleted` bit(1) NOT NULL,
`version` int(11) DEFAULT NULL,
`pid` bigint(20) NOT NULL,
`qid` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK8FEA83DBE860AF9` (`pid`),
KEY `FK8FEA83DBF34C20F6` (`qid`),
CONSTRAINT `FK8FEA83DBE860AF9` FOREIGN KEY (`pid`) REFERENCES `parent` (`id`),
CONSTRAINT `FK8FEA83DBF34C20F6` FOREIGN KEY (`qid`) REFERENCES `question` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8
I have the right to insert one row in the question table.So when I add a new row then id will be generated (because it is auto_increment) and I want to store this id in the qid field parent_question table.
Can anybody please tell me how to do it?
Use the last_insert_id() function:
insert into question values (...);
insert into parent_question values (..., last_insert_id(), ...);