Should I use Inner Join in this case? - mysql

I am working on a student attendance mini-project, and I don't know how to proceed for my database. I'm new to SQL and databases in general so this might seem dumb to you.
So, I want to do a database containing the table student, which contains : student_id (primary key) , name (string) and attendance(boolean) (that's the bare minimum, i'll add more afterwards) and I want to register the daily attendance of the students. So I want to have all the students tied to every date of the week.
I created a date table in phpMyadmin but I don't know how to proceed to link them, i've tried an Inner Join and it was successful.
The problem is : If i want to add another line to the student table my table won't update, so is there a way to "automatically" tie all the students to the date table ?
Sorry if this seems confused I've tried my best to summarize it !

Lets have some idea about tables should be there to implement a proper Student Attendance system in place. I have copied create script for some of my tables that used for maintaining Students record per course. I hope following sample Table scripts with relation will help you understanding regarding table structure and also to solve your issue.
Please be noted, That this table structures for your your reference only. You can add/remove tables/columns as per your requirement once you get an overall idea from this post.
CREATE TABLE `staff` (
`id` int(11) NOT NULL,
`type` varchar(200) DEFAULT NULL,
`first_name` varchar(200) DEFAULT NULL,
`last_name` varchar(200) DEFAULT NULL,
`emal` varchar(200) DEFAULT NULL,
`contact` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `batch` (
`id` int(11) NOT NULL,
`department` varchar(200) DEFAULT NULL,
`details` varchar(200) DEFAULT NULL,
`staff_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `batch_staff_idx` (`staff_id`),
CONSTRAINT `batch_staff` FOREIGN KEY (`staff_id`) REFERENCES `staff` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `student` (
`id` int(11) NOT NULL,
`batch_id` int(11) DEFAULT NULL,
`first_name` varchar(200) DEFAULT NULL,
`last_name` varchar(200) DEFAULT NULL,
`email` varchar(200) DEFAULT NULL,
`contact` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `batch_student_idx` (`batch_id`),
CONSTRAINT `batch_student` FOREIGN KEY (`batch_id`) REFERENCES `batch` (`batch_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `course` (
`id` int(11) NOT NULL,
`name` varchar(200) DEFAULT NULL,
`details` varchar(200) DEFAULT NULL,
`staff_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `course_staff_idx` (`staff_id`),
CONSTRAINT `course_staff` FOREIGN KEY (`staff_id`) REFERENCES `staff` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `attendence` (
`course_id` int(11) NOT NULL,
`student_id` int(11) DEFAULT NULL,
`class_date` date DEFAULT NULL,
KEY `att_course_idx` (`course_id`),
KEY `att_student_idx` (`student_id`),
CONSTRAINT `att_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `att_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Your required data will finally store into table Attendance. From this table data, you will be able to find list of students absent/present per date and per course. Remember, the attendance table should enrich daily from a automated OR a manual process.

Related

Foreign key constraint fails with Insert Into Select in MySQL

I'm quite new to SQL, and I'm trying to upload data to my tables. For this I have special tables where I upload the data from a CSV file, and then, from this table, I am trying to copy the data to the final table.
But now I have a problem with an intermediate table where I have uploaded my data. The table is:
CREATE TABLE `_work_has_person` (
`work_id` int(11) NOT NULL,
`person_id` int(11) NOT NULL,
`primary_contribution_id` int(11) DEFAULT NULL,
PRIMARY KEY (`work_id`,`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I want to copy the data in
CREATE TABLE `work_has_person` (
`work_id` int(11) NOT NULL,
`person_id` int(11) NOT NULL,
`primary_contribution_id` int(11) NOT NULL,
PRIMARY KEY (`work_id`,`person_id`),
KEY `fk_work_has_person_person1_idx` (`person_id`),
KEY `fk_work_has_person_work1_idx` (`work_id`),
KEY `fk_work_has_person_primary_contribution1_idx` (`primary_contribution_id`),
CONSTRAINT `fk_work_has_person_person1` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_work_has_person_primary_contribution1` FOREIGN KEY (`primary_contribution_id`) REFERENCES `primary_contribution` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_work_has_person_work1` FOREIGN KEY (`work_id`) REFERENCES `work` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Which is an intermediate table between:
CREATE TABLE `work` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title_work` varchar(250) DEFAULT NULL,
`subtitle_work` varchar(250) DEFAULT NULL,
`date_work` varchar(45) DEFAULT NULL,
`unix_date_work` varchar(100) DEFAULT NULL,
`sinopsis` text,
`ref_bne` varchar(100) DEFAULT NULL,
`ref_alt` longtext,
`language_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_work_language1_idx` (`language_id`),
KEY `title_work` (`title_work`),
CONSTRAINT `fk_work_language1` FOREIGN KEY (`language_id`) REFERENCES `language` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=24610 DEFAULT CHARSET=utf8;
and
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`img_person` varchar(250) DEFAULT NULL,
`born_date` varchar(45) DEFAULT NULL,
`unix_born_date` varchar(100) DEFAULT NULL,
`city_born_date` varchar(100) DEFAULT NULL,
`country_born_date` varchar(100) DEFAULT NULL,
`death_date` varchar(45) DEFAULT NULL,
`unix_death_date` varchar(100) DEFAULT NULL,
`city_death_date` varchar(100) DEFAULT NULL,
`country_death_date` varchar(45) DEFAULT NULL,
`biography` longtext,
`ref_bne` varchar(100) DEFAULT NULL,
`ref_alt` longtext,
PRIMARY KEY (`id`),
UNIQUE KEY `name_UNIQUE` (`name`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=9159 DEFAULT CHARSET=utf8;
But everytime I try to run
INSERT INTO work_has_person (work_id, person_id, primary_contribution_id)
SELECT work_id, person_id, primary_contribution_id
FROM _work_has_person;
It says
Cannot add or update a child row: a foreign key constraint fails (`cdu93hfg93r`.
`work_has_person`, CONSTRAINT `fk_work_has_person_person1` FOREIGN KEY (`person_id`)
REFERENCES `person` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
I am pretty sure that the tables has the neccesary data, but, ¿is there a way to know which data fails? I have seen Mysql error 1452 - Cannot add or update a child row: a foreign key constraint fails: but don't understand exactly how to use it here.
A.
It is relatively easy to find out what data is causing the conflict: get all person_ids from _work_has_person that are not in the persons table. You can achieve this via an outer join and filtering for person.id is null in the where clause.
select * from `_work_has_person` whp
left join person p on whp.person_id=p.id
where p.id is null
You can actually remove such data from the results being inserted by including the reverse criterion into the select part of your insert query (an inner join):
INSERT INTO work_has_person (work_id, person_id, primary_contribution_id)
SELECT whp.work_id, whp.person_id, whp.primary_contribution_id
FROM _work_has_person whp
INNER join person p on whp.person_id=p.id

Only allow one unique foreign key for primary

I have 3 tables in mysql, One is a Company table, the other is a license table and the last is a joining table between both primary keys, When a person adds a company id to the license id in the joining table, it allows multiple companies to exist for one license, this cannot happen, so I need to do something that will only allow one company id for one license id
heres the tables
Table license
CREATE TABLE `License` (
`license_id` int(11) NOT NULL AUTO_INCREMENT,
`license_number` varchar(45) NOT NULL,
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`duration` int(11) NOT NULL,
`expiry_date` date NOT NULL,
`product_id` int(11) DEFAULT NULL,
PRIMARY KEY (`license_id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
;
Company Table
CREATE TABLE `Company` (
`company_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`physical_address` varchar(255) DEFAULT NULL,
`postal_address` varchar(255) DEFAULT NULL,
`reseller_id` int(11) DEFAULT NULL,
PRIMARY KEY (`company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin1;
and Joining table
CREATE TABLE `CompanyLicense` (
`license_id` int(11) NOT NULL,
`company_id` int(11) NOT NULL,
PRIMARY KEY (`license_id`,`company_id`),
KEY `companlicence_company_fk_idx` (`company_id`),
CONSTRAINT `companylicense_company_fk` FOREIGN KEY (`company_id`) REFERENCES `Company` (`company_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `companylicense_license_fk` FOREIGN KEY (`license_id`) REFERENCES `License` (`license_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
So far i have this
INSERT INTO CompanyLicense (license_id, company_id) VALUES
('2','6') on duplicate key update license_id = '2';
doesnt seem to do the job
You need to make company unique in companylicense:
ALTER TABLE companylicense ADD UNIQUE KEY (company)
or better yet, make company a field in license instead of having a link table.

using foreign keys with mysql

I have a forgiven key issue using MySQL. I have a studies table and a samples table. Users can add studies and also add samples. every sample belongs to a study, but studies can have many samples. So theres a one to many relationship with studies and samples. I need to set up a foreign key in the samples table so that whenever a new sample is created it can be referenced by its parent study. I set up a foreign key in the sample table with this script below, but whenever I add a new sample it leaves the study_id column empty. I’m new using foreign keys so any examples would be great. Thanks.
CREATE TABLE `studies` (
`study_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`study_name` varchar(45) DEFAULT NULL,
`description` tinytext,
`reads` varchar(45) DEFAULT NULL,
`created_at` varchar(45) DEFAULT NULL,
PRIMARY KEY (`study_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
CREATE TABLE `samples` (
`sample_id` int(11) NOT NULL AUTO_INCREMENT,
`study_id` int(11) DEFAULT NULL,
`sample_name` varchar(45) DEFAULT NULL,
`created_at` varchar(45) DEFAULT NULL,
PRIMARY KEY (`sample_id`),
FOREIGN KEY (`study_id`)
REFERENCES `studies` (`study_id`)
ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

MYSQL on delete cascade example

I can't figure out how to use on delete cascade in my example.
CREATE TABLE `users` (
`login` varchar(16) NOT NULL,
`password` varchar(16) NOT NULL,
PRIMARY KEY (`login`),
UNIQUE KEY `login` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `employees` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
`Surname` varchar(25) NOT NULL,
`Birthday` date NOT NULL,
`Adres` varchar(50) NOT NULL,
`Telephone` varchar(25) NOT NULL,
`login` varchar(16) DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `login` (`login`),
CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`login`) REFERENCES `users` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
One table stores informations about employee and if he has account(login) there is another table with logins and passwords.
My goals:
Not every employee needs to have user account(that means - unique record in Users table) so Employees.Login shouldn't be restricted with NOT NULL.
I want possiblity to add new user in Users and then assign it to some employee.
When I delete employee, related unique user is also deleted(if he had one).
First two are already done. I don't know how to make 3 happen now.
You've put the CONSTRAINT in the wrong CREATE TABLE statement. It goes on the referencing table, which is "users", because that's the table you want to automatically delete from when a row in the other table is deleted.
You want to put a nullable "ID" in the "users" table, which is unique and a foreign key to "employees".
Use this query :
CREATE TABLE `users` (
`login` varchar(16) NOT NULL,
`password` varchar(16) NOT NULL,
PRIMARY KEY (`login`),
UNIQUE KEY `login` (`login`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `employees` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
`Surname` varchar(25) NOT NULL,
`Birthday` date NOT NULL,
`Adres` varchar(50) NOT NULL,
`Telephone` varchar(25) NOT NULL,
`login` varchar(16) DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `login` (`login`),
CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`login`) REFERENCES `users` (`login`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Based on suggestion from Hammerite now my tables definion looks like this:
CREATE TABLE `employees` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
`Surname` varchar(25) NOT NULL,
`Birthday` date NOT NULL,
`Adres` varchar(50) NOT NULL,
`Telephone` varchar(25) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `users` (
`login` varchar(16) NOT NULL,
`password` varchar(16) NOT NULL,
`employee_id` int(11) NOT NULL,
PRIMARY KEY (`login`),
UNIQUE KEY `login` (`login`),
UNIQUE KEY `employee_id` (`employee_id`),
CONSTRAINT `users_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `employees` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
I have deleted login column from employees table
I have created another column employee_id in User table. It's unique foreign key and cannot be null since I dont want user accounts that are not used by anybody.
Now If I do this:
INSERT INTO users VALUES('login123','password',2);
then this row will be deleted after I do this:
DELETE FROM employees WHERE id=2;
I was sure that I need to make some reference in employees table to users table, thats why I didn't think about solution like this.
THANKS!

Help with my table structure

I'm trying to make an address book. And have made my tables like this:
CREATE TABLE `list_`.`contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` tinyint(11) NOT NULL,
`group` varchar(128) NOT NULL,
`first_name` varchar(128) NOT NULL,
`last_name` varchar(128) NOT NULL,
`address` varchar(128) NOT NULL,
`city` varchar(128) NOT NULL,
`state` varchar(2) NOT NULL,
`zip` int(5) NOT NULL,
`phone_number` varchar(16) NOT NULL,
`cell_number` varchar(16) NOT NULL,
`work_number` varchar(16) NOT NULL,
`fax_number` varchar(16) NOT NULL,
`email` varchar(128) NOT NULL,
`company` varchar(55) NOT NULL,
`title` varchar(56) NOT NULL,
`notes` text NOT NULL,
`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`user_id`),
KEY `user_id` (`user_id`),
KEY `group` (`group`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
CREATE TABLE `list_`.`groups` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` tinyint(11) NOT NULL,
`position` int(8) unsigned NOT NULL DEFAULT '0',
`name` varchar(128) NOT NULL,
`date_added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`user_id`),
KEY `user_id` (`user_id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8 AUTO_INCREMENT=32 ;
My logic here is that I have all the contacts in the contacts table, from there I have a column called group that I use to filter the contacts into groups.
Then I have a table called groups that I'll use to keep track of what groups where created by a specific user and fill a with these groups so they can move the contacts around.
When a group is deleted I will throw back an error no letting it be deleted if the group contains contacts. I can probably query the contacts to see what group they belong to and if they belong to the group being deleted then I'll move them into a group called Uncategorized or something.
But if they choose to accept and delete ALL contacts within a group then go ahead and delete the group and all child rows that belong to that group.
I am having trouble creating my Foreing Keys in the contacts table. No matter what combination of index and keys I try I still can't make it work.
--
-- Constraints for table `contacts`
--
ALTER TABLE `list_`.`contacts`
ADD CONSTRAINT `contacts_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
ADD CONSTRAINT `contacts_ibfk_2` FOREIGN KEY (`group`) REFERENCES `groups` (`name`) ON UPDATE CASCADE;
--
-- Constraints for table `groups`
--
ALTER TABLE `list_`.`groups`
ADD CONSTRAINT `group_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`);
Also, can someone help me with the ON DELETE and ON UPDATE. To help me figure out how I can delete all child rows that reference the name column in groups
I do not think you should have MySQL do so much heavy lifting, specifically deleting a group if it is empty. Is there any specific reason to do this, i.e. can the group no longer be used if it is empty? You could probably achieve this with mysql triggers if you really wanted to.
As for preventing the deletion of a group that is simply done by the foriegn key on contacts that you already have on groups. However I highly recommend that you use ids rather than names for keys.
What you are saying seems to conflict, however: you want to prevent deletion of a group that has contacts, but you want all contacts in a group to be deleted when the group is deleted?