how to define foreign key constraints - mysql

I have three mysql tables. Tables are already created.
Requests - request_id, request_message, user_id
Responses - response_id, response_message, user_id
users - user_id, user_name
Now i want to define foreign key constraints on that, such that
1. If user_id is not present in Users table, and someone is inserting the data in Requests or Responses for that user_id -- then error
2. If request_id is not present in Requests table, then if someone is inserting in responses table for that request_id -- then error
3. If someone deletes an user_id, all associated requests and responses with that user_id should be deleted automatically.
4. If someone deletes an request_id, all the associated responses with it, should be deleted automatically.
If i am missing any thing please let me know.
How to achieve this functionality?
Thanks
Devesh

Here is full sql to create your tables:
CREATE TABLE IF NOT EXISTS `reponses` (
`response_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`response_message` varchar(45) DEFAULT NULL,
`user_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`response_id`,`user_id`),
KEY `fk_reponses_users1` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `requests` (
`request_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`request_message` varchar(45) DEFAULT NULL,
`user_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`request_id`,`user_id`),
KEY `fk_requests_users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=3 ;
ALTER TABLE `reponses`
ADD CONSTRAINT `reponses_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `requests`
ADD CONSTRAINT `requests_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE NO ACTION;
Option that allows you to delete records related to user is ON DELETE CASCADE. By default MySql sets NO ACTION which refers to RESTRICT and doesn't allow parent record to be deleted while it has related objects. I think that you didn't mention the relation between responses and requests but you should get the idea ;).

Related

MySQL: 1:n relationship with auto increasing PK

I've two tables: users and files. A user can create files (1:n relationship).
When a user is deleted, all the user files refered to the user should be deleted, too. Deleting single files of a user should also be possible.
Try 1
CREATE TABLE `users` (
`user_id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`password` VARCHAR(60) NOT NULL,
`salt` VARCHAR(33) NOT NULL,
`user_group_id` INT NOT NULL,
PRIMARY KEY (`user_id`),
CONSTRAINT `fk_u_user_group` FOREIGN KEY (`user_group_id`) REFERENCES `user_groups` (`user_group_id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `user_file` (
`user_id` INT NOT NULL,
`user_file_id` INT NOT NULL,
`name` VARCHAR(50) NOT NULL,
`content` JSON DEFAULT NULL,
PRIMARY KEY ( `user_id`, `user_file_id`),
CONSTRAINT `fk_uf_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE ON DELETE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
The table user_files contains files of all users so the primary key have to be a composition of user_id and user_file_id.
This solution works for me but there is one problem: The user_file_id is not increased automatically (because it's not the primary key). But I do not want to know the user_file_id when inserting new files to the table.
INSERT INTO user_files VALUES(1, ???, 'New file', default)
The default keyword instead of ??? is not working here.
Try 2
Another solution I though of would be to create a new table user_user_files that merges the tables users and user_files.
CREATE TABLE `user_file` (
`user_file_id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`content` JSON DEFAULT NULL,
PRIMARY KEY (`user_file_id`),
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `user_user_files`(
`user_id` INT NOT NULL,
`user_file_id` INT NOT NULL,
PRIMARY KEY(`user_id`, `user_file_id`),
CONSTRAINT `fk_uuf_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `fk_uuf_user_file_id` FOREIGN KEY (`user_file_id`) REFERENCES `user_files` (`user_file_id`) ON UPDATE CASCADE ON DELETE CASCADE
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
With that I could create a trigger when inserting a new row into user_files and that trigger would add a new row to user_user_files.
DELIMITER $$
CREATE TRIGGER after_user_insert
AFTER INSERT
ON user_files FOR EACH ROW
BEGIN
INSERT INTO `user_user_files` VALUES(NEW.user_file_id,default, default);
END$$
DELIMITER ;
But is this possible when I want the following behavior?
Delete all user files when the user is deleted
Option to delete single user files from a user
Summary
So with try 1 there is the problem that the primary key is not increased automatically.
With try 2 I do not know if my desired behavior works with deleting / adding rows.

foreign key shall automatically create a new entry

I have 2 tables users and iom.
Primary key of users is iomid and of course in iom the foreign key is iomid that references users.iomid.
If i create a new user in users, I want it automatically inserted into iom aswell without making a second statement.
How can I do it?
iom:
CREATE TABLE IF NOT EXISTS `iom` (
`id` int(11) NOT NULL,
`iomid` varchar(50) NOT NULL,
`subscribed` int(11) DEFAULT NULL,
`workoutcounter` int(11) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
ALTER TABLE `iom`
ADD UNIQUE KEY `id` (`id`), ADD KEY `iom_ibfk_1` (`iomid`);
ALTER TABLE `iom`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `iom`
ADD CONSTRAINT `iom_ibfk_1` FOREIGN KEY (`iomid`) REFERENCES `users` (`iomid`) ON DELETE CASCADE ON UPDATE CASCADE;
user:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL,
`iomid` varchar(50) NOT NULL,
`name` varchar(50) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
ALTER TABLE `users`
ADD PRIMARY KEY (`iomid`), ADD UNIQUE KEY `id` (`id`);
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Thanks and greetings!
Now that I look at your question again, the issues with your foreign key conventions are fairly irrelevant. Even with more typical relations, foreign key constraints cannot create rows; at most, they can "cascade" updates and deletes of referenced values to referencing tables.
What you need is an "AFTER INSERT ON users" trigger. (Documentation here.)

Creating foreign key between 2 tables

Ok, so it's like this. I have 2 tables in phpmyadmin. One is for personal details and the other is for login information. Both tables have AccountID, so I tried using foreign key constraints to connect the tables. After I did that it seems like I cannot update the table with new data. Before the constraint, updating the tables worked fine.
What I'm trying to do is store user login info and personal info in these table. Then whenever the user wants to delete their current account, the personal details and login details of are deleted from both tables or when they wanted to search for their login and personal info the search engine can search from both tables with AccountID.
so far.i have make 2 new tables.1 table which is personal information have 'AccountID'[A_I][PRIMARY] and 'loginID'.another table is login info.it has 'loginID'[A_i][PRIMARY]
i already make the 'loginID' at personal info and index but i cannot assign foreign key constraint for it bcause it did not detect 'loginID' in personal info.
Your AccountId should be a primary key in one table say Personal Info table.
This AccountId should be the foreign key in another table (Login) and make sure you set on Delete Cascade and on Update Cascade.
So in this structure, when personal info is deleted, its corresponding record in the login table will be automatically deleted.
DROP TABLE IF EXISTS `stacktest`.`personal_info`;
CREATE TABLE `stacktest`.`personal_info` (
`account_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
`age` varchar(45) DEFAULT NULL,
PRIMARY KEY (`account_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `stacktest`.`login_info`;
CREATE TABLE `stacktest`.`login_info` (
`loginId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`account_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`loginId`),
KEY `FK_login_info_1` (`account_id`),
CONSTRAINT `FK_login_info_1` FOREIGN KEY (`account_id`) REFERENCES `personal_info` (`account_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
Above is the way how the 2 tables should be created.
Then insert some values in both table,
Note that account_id value has to be same in both the tables.
After that you can fire a delete query like:
delete from personal_info where accound_id=2;
This will delete rows from parent table personal_info and also from child table login_info where account_id is 2
Keeping the account_id as NOT NULL in child table:
DROP TABLE IF EXISTS `stacktest`.`login_info`;
CREATE TABLE `stacktest`.`login_info` (
`loginId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`account_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`loginId`),
KEY `FK_login_info_1` (`account_id`),
CONSTRAINT `FK_login_info_1` FOREIGN KEY (`account_id`) REFERENCES `personal_info` (`account_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

MySQL foreign key ON DELETE SET NULL check data types error

I'm working on a normalised database, to be secure I wanted to use foreign keys.
My database:
CREATE TABLE `names` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `name_2` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name_id` (`name_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
The command:
ALTER TABLE `names` ADD FOREIGN KEY ( `name` ) REFERENCES `temp`.`users` (
`name_id`
) ON DELETE SET NULL ON UPDATE CASCADE ;
The response (error):
Error creating foreign key on name (check data types)
So, how to fix this?
The error is self explanatory. Name in names table is of type varchar(250) whereas name_id in users table is of type int(11).
But I believe you meant to have an FK all the way around in users table referencing names table.
ALTER TABLE users
ADD FOREIGN KEY (name_id) REFERENCES names (id)
ON DELETE SET NULL ON UPDATE CASCADE;
Here is SQLFiddle demo
Both keys have to be the same type and length,you have varchar and int.
Here is what you want:
ALTER TABLE `names` ADD FOREIGN KEY ( `id` ) REFERENCES `users` (
`name_id`)

Foreign key doesn't keep data consistency

Many days ago I made a database which had two tables:
member(member_id(PK),name)
account(account_id(PK),member_id(FK),amount).
So Normally I cant DELETE any member if member have balance in account table . Before it was work well.
But today I import same script and I can delete a member even member have balance in account table.
I don't know what happends? I don't remember previous server version of mysql. Now I am running mysql 5.5.16 and MySQL client version is mysqlnd 5.0.8-dev - 20102224 - Revision: 310735 in localhost.
my code is
//account table
CREATE TABLE IF NOT EXISTS `account` (
`account_id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL,
`dates` date NOT NULL,
`amount` float NOT NULL,
PRIMARY KEY (`account_id`),
KEY `FK_account_1` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
//member table
CREATE TABLE IF NOT EXISTS `member` (
`member_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`account_num` int(11) NOT NULL,
PRIMARY KEY (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=34 ;
//and this code
ALTER TABLE `account`
ADD CONSTRAINT `FK_account_1`
FOREIGN KEY (`member_id`)
REFERENCES `member`(`member_id`)
ON DELETE CASCADE
ON UPDATE CASCADE;
I'm not sure if I understand this well but:
The constraint you have means that every time you delete a member, the member will be deleted together with any balance it has in the account table. (ON DELETE CASCADE)
If this is not your desired behavior, and you want mysql to raise an exception when deleting a member that has a balance; then just remove the ON DELETE CASCADE line from your constraint definition.
ALTER TABLE account
ADD CONSTRAINT `fk_account_member`
FOREIGN KEY (`member_id`)
REFERENCES `member` (`member_id`)
ON DELETE CASCADE
ON UPDATE CASCADE;