MySQL Unique Index between three tables - mysql

I have the schema of the following tables:
CREATE TABLE IF NOT EXISTS `depts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`deptName` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `deptUniq` (`deptName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `sub_depts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dept_id` int(11) NOT NULL,
`subDeptName` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `subDeptNameUniq` (`subDeptName`),
KEY `keyDept` (`dept_id`),
CONSTRAINT `keyDept` FOREIGN KEY (`dept_id`) REFERENCES `depts` (`id`) ON DELETE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `objects` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sub_depts_id` int(11) NOT NULL,
`objName` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `objNameUniq` (`objName`),
KEY `keySubDept` (`sub_depts_id`),
CONSTRAINT `keySubDept` FOREIGN KEY (`sub_depts_id`) REFERENCES `sub_depts` (`id`) ON DELETE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
relationship between tables sub_depts and depts many-to-one
relationship between tables objects and sub_depts many-to-one
relationship between tables objects and depts must be one-to-one
if the tables objects and depts was one table a simple UNIQUE index (objName, deptName) would work
but need to keep the three tables separate
example data:
depts
1 dept1
2 dept2
sub_depts
1 1 subDept1
2 1 subDept2
3 2 subDept3
objects
1 1 obj1
after execute next line:
INSERT INTO `objects` (`sub_depts_id`, `objName`) VALUES (2, "obj1");
must be the error because not unique data
after execute next line:
INSERT INTO `objects` (`sub_depts_id`, `objName`) VALUES (3, "obj1");
success
Could you help me update the schema of the table, please?
I am using the latest version of MySQL. Thank you for your answers.

Related

How to make working: FOREIGN KEY error during addition

I have two tables, books and borrowing requests - I am making a study project to learn MySQL. Trying to link these two tables using a FK, and constantly get an error:
"SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint")
Apart from documentation, I searched virtually all of the related topics here on SO, however, no success. Types are the same, columns both unsigned, one primary key, etc. - to my understanding I have respected all of the provisions. But it does not work! What am I missing?
Here are the two tables and the fk addition query:
CREATE TABLE `books` (
`book_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`book_title` VARCHAR(100) NOT NULL,
`author_id` INT(11) NOT NULL,
`book_condition` INT(5) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=23453 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `borrowing_requests` (
`request_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`user_id` INT(11) NOT NULL,
`book_id` INT(11) UNSIGNED NOT NULL,
`due_date` VARCHAR(55) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=23453 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
FK Query:
ALTER TABLE `books` ADD CONSTRAINT books_fk FOREIGN KEY (`book_id`)
REFERENCES `borrowing_requests`(`book_id`)
ON DELETE NO ACTION ON UPDATE NO ACTION
You have the foreign key "backwards" - the borrowing request should reference a book, not the other way round:
ALTER TABLE `borrowing_requests` ADD CONSTRAINT books_fk FOREIGN KEY (`book_id`)
REFERENCES `books`(`book_id`)
ON DELETE NO ACTION ON UPDATE NO ACTION

Can't add foreign key in MySQL Database

Trying to create a simple relation between two fields in two tables - 'Task' table with the field 'USER_TOKEN' and the 'USER' table with the field 'TOKEN'. The two fields are the same structure. As you can see the error and other things that may assist you to help me understand the problem and fix it.
System: MacOS 10.12.3 | DB : MySQL 5.7.17 | DBM : Sequel Pro
Error : MySQL said: Cannot add foreign key constraint
CREATE TABLE `TASK` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`USER_TOKEN` int(11) unsigned NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `USER` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`TOKEN` int(11) unsigned NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE USER
ADD CONSTRAINT TOKENS
FOREIGN KEY (`TOKEN`) REFERENCES `category`(`USER_TOKEN`)
Thanks.
If you really want to create a foreign key to a non-primary key, it MUST be a column that has a unique constraint on it.
A FOREIGN KEY constraint does not have to be linked only to a PRIMARY KEY constraint in another table; it can also be defined to reference the columns of a UNIQUE constraint in another table.
So your USER_TOKEN column of table TASK and TOKEN column of USER table must be UNIQUE. So run the following query:
CREATE TABLE `TASK` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`USER_TOKEN` int(11) unsigned NOT NULL UNIQUE,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `USER` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`TOKEN` int(11) unsigned NOT NULL UNIQUE,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `USER`
ADD CONSTRAINT `TOKENS`
FOREIGN KEY (`TOKEN`) REFERENCES `TASK`(`USER_TOKEN`);
Check Demo here

determine a database relationship

I need help to decide if the relationship between this 2 table is one to many or many to many. One student can sign up for many class and one class can have multiple student. This is my table below:
Thankyou
This is how it should be:
classes to students is in HABTM Relationship maped by classes_students.
Below is schema:
CREATE TABLE `students` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
CREATE TABLE `classes` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`subject` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
CREATE TABLE `classes_students` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`class_id` INT(11) NOT NULL,
`student_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK__classes` (`class_id`),
INDEX `FK__students` (`student_id`),
CONSTRAINT `FK__classes` FOREIGN KEY (`class_id`) REFERENCES `classes` (`id`),
CONSTRAINT `FK__students` FOREIGN KEY (`student_id`) REFERENCES `students` (`id`)
)
COMMENT='table to support HABT classes to students'
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
This is a many-to-many relationship. You need to have Students and Classes into separate tables and connect them via a junction table which will contain a student_id and a class_id.

Getting data that is difficult connected with the input data, SQL Query

Firstly, want to ask you (so my question would be more clear for you) if there an online database diagram tool (?) in which I can input my sql code and it will draw diagramm (with tables and their relationships) for me.
I found this question and tried some tools, but most of them can only create tables and relationships between them, but not allow to import my sql.
(2)
I need to get all classes connected with Teacher.
There are two types of connection: teacher may be the form-master or teacher may taugh this class.
How to get all classes which are connected to teacher.
(3) 1 more additional question: Am I right with constraints?
SQL Scheme (scheme on sqlfiddle.com):
CREATE TABLE `Subject` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
CREATE TABLE `Teacher` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`firstname` VARCHAR(50) NOT NULL,
`midname` VARCHAR(50) NOT NULL,
`lastname` VARCHAR(50) NOT NULL,
`address` VARCHAR(100) NOT NULL,
`birthdate` DATE NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `Class` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`digit` INT(11) NOT NULL,
`char` VARCHAR(50) NOT NULL,
`teacher_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_Class_Teacher` (`teacher_id`),
CONSTRAINT `FK_Class_Teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`)
);
CREATE TABLE `ClassVsSubject` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`subject_id` INT(11) NOT NULL,
`class_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `subject_id_class_id` (`subject_id`, `class_id`),
INDEX `FK_ClassVsSubject_Class` (`class_id`),
CONSTRAINT `FK_ClassVsSubject_Class` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`),
CONSTRAINT `FK_ClassVsSubject_Subject` FOREIGN KEY (`subject_id`) REFERENCES `subject` (`id`)
);
CREATE TABLE `TeacherVsSubject` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`teacher_id` INT(11) NOT NULL,
`subject_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_TeacherVsSubject_Teacher` (`teacher_id`),
INDEX `FK_TeacherVsSubject_Subject` (`subject_id`),
CONSTRAINT `FK_TeacherVsSubject_Teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`),
CONSTRAINT `FK_TeacherVsSubject_Subject` FOREIGN KEY (`subject_id`) REFERENCES `subject` (`id`)
);
For your second question, use something like:
select *
from Class
where teacher_id = 1
union
select Class.*
from Class
join ClassVsSubject on Class.id = ClassVsSubject.class_id
join TeacherVsSubject on ClassVsSubject.subject_id = TeacherVsSubject.subject_id
where TeacherVsSubject.teacher_id = 1
As you did not state which teacher is the starting point, I used that with id 1.
Please note that union gets rid of duplicate entries, there is no need to treat this separately.
For your data model (question 3), I think one gotcha is that you need different entries in the subject table for different classes and the same subject like 'Maths' or 'English', otherwise, the joins will not work:
Let's say subject "English" has id 1. Now, if the class with id 1 and the class with id 2 both have this subject, you would have the following data in ClassVsSubject:
class_id subject_id
1 1
2 1
How do you want to enter into table TeacherVsSubject that the teacher with id 5 teaches English in class 1, but not in class 2? You cannot! If you enter a record with subject_id 1 and teacher_id 5, this would apply to all classes.
To remedy that, you could make one table from the two ClassVsSubject and TeacherVsSubject. This would be like this:
CREATE TABLE `ClassVsSubjectVsTeacher` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`subject_id` INT(11) NOT NULL,
`class_id` INT(11) NOT NULL,
`teacher_id` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `subject_id_class_id` (`subject_id`, `class_id`, `teacher_id`),
INDEX `FK_ClassVsSubjectVsTeacher_Class` (`class_id`),
INDEX `FK_ClassVsSubjectVsTeacher_Teacher` (`teacher_id`),
INDEX `FK_ClassVsSubjectVsTeacher_Subject` (`subject_id`),
CONSTRAINT `FK_ClassVsSubjectVsTeacher_Class` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`),
CONSTRAINT `FK_ClassVsSubjectVsTeacher_Teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`),
CONSTRAINT `FK_ClassVsSubjectVsTeacher_Subject` FOREIGN KEY (`subject_id`) REFERENCES `subject` (`id`)
);
For the data model, you would not need the id column here, the primary key could be a combined key across all three foreign keys. But - depending on client software - it may be useful to have it. E. g. some OR mapping tools require a single column primary key.
Try this: select * from Class where teacher_id = some_id_from_Teacher_table

mysql cannot create foreign key

here are my two tables
CREATE TABLE IF NOT EXISTS `carslibrary` (
`CarID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`CarName` varchar(255) NOT NULL,
`colorslibrary_ID` int(11) unsigned NOT NULL,
PRIMARY KEY (`CarID`),
KEY `colorslibrary_ID` (`colorslibrary_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
CREATE TABLE IF NOT EXISTS `colorslibrary` (
`ColorID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`ColorName` varchar(255) NOT NULL,
PRIMARY KEY (`ColorID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
I get an error on the following query:
ALTER TABLE `carslibrary` ADD FOREIGN KEY ( `colorslibrary_ID` )
REFERENCES `cars2`.`colorslibrary` (`ColorID` );
MySQL says:
#1452 - Cannot add or update a child row: a foreign key constraint
fails (`cars2`.<result 2 when explaining filename
'#sql-cf8_41a'>, CONSTRAINT `#sql-cf8_41a_ibfk_1` FOREIGN KEY
(`colorslibrary_ID`) REFERENCES `colorslibrary` (`ColorID`))
Your tables aren't empty, therefore a constraint fails (reference not found) when you create it.
Use SET FOREIGN_KEY_CHECKS = 0; and re-run your alter table.
I would firstly identify orphaned rows in the carslibrary table:
select * from carslibrary where colorslibrary_ID not in (select ColorID from cars2.colorslibrary);
Then decide what you want to do with these orphaned rows. Want to DELETE them from the carslibrary table? UPDATE them to an existing parent ColorID in the colorslibrary? INSERT a new ColorID in the colorslibrary table to cater for the orphaned rows?
Once you've tidied up your data you should be able to run the ALTER TABLE with no errors.