SQL: delete from joint tables where count condition - mysql

I have these tables:
tutors:
email firstname, lastname...
courses:
url tutorid description
reviews:
review courseid author
author in reviews and tutorid in courses is foreign key = tutors.email.
I need to delete all tutors that have 2 or more courses without a description.
I first tried to just select such tutors:
select tutors.email, COUNT(courses.url)
from courses
left join tutors on courses.tutorid = tutors.email
where
description is null group by (tutors.email);
this works fine. However I'm not sure how to delete the tutors with the given emails, considering the tutors.email is a foreign key in other tables.

If you don't delete the records in related tables that contains the foreign key, you will eventually create something called orphaned records, and that is something that goes against the referential integrity rule in general in RDBMS.
It is also possible that the RDBMS will enforce referential integrity, and you wont be able to do that before you delete all the associate records in the other tables first.

Related

Is it possible to have multiple many-to-many relationships between the same two tables?

I have a few tables that need to be joined together multiple times but I'm not sure if there can be multiple join tables for the same two tables. The tables i have are as follows:
User
Group
Record
Id PK
Id PK
Id PK
Name
Name
Name
etc
etc
Date
GroupID FK
//A record can only belong to 1 group
UserID FK
//A record can only have 1 creator/admin
I then want to have two join tables that can keep track of which group a user is a member of, and which member is an admin of the group.
Group Members
Group Admins
GroupID
GroupID
UserID
UserID
A Group can have many members while a user can be a member of many groups.
A Group can have many admins while a user can be an admin of many groups.
I get an error when trying to create the foreign keys for the "Group Members" and "Group Admins" tables.
SQL Query: "ALTER TABLE GroupMembers ADD CONSTRAINT GroupId FOREIGN KEY (GroupId) REFERENCES Group(Id);"
SQL Error: "Error creating foreign key on GroupId (check data types)"
Is this possible or is there a better way of doing this?
While updating the question, I found that there were restrictions being placed on the foreign keys by my workbench which was causing the error. The solution was to remove the "on delete" and "on update" restrictions.

Foreign Key settings with regards to bridging tables

I have a question on foreign key settings with regards to bridging tables. I still am unsure of how the deletion process works. My foreign keys are currently all set to On Delete: No Action, so does that mean that in the case of a bridging table, in order to delete records in one or both of the parent tables, I would have to delete the records they feature in in the bridging table first or does it work differently with many-to-many relationships? Apologies if this is a simple, dumb question but it seems pretty difficult for someone new to databases to find clear, simple, easy-to-follow documentation anywhere to explain these things.
The rule is pretty straightforward:
You can't delete a row if some other row exists that references the one you want to delete.
Example: A college photography course is created as a row in the courses table.
INSERT INTO courses SET course_id = 1234, title = 'Photography';
People enroll in the course:
INSERT INTO enrollments SET course_id = 1234, student_id = 9877;
INSERT INTO enrollments SET course_id = 1234, student_id = 9876;
INSERT INTO enrollments SET course_id = 1234, student_id = 9875;
Then the instructor wants to cancel the course.
DELETE FROM courses WHERE course_id = 1234;
This is blocked, because there are rows in enrollments that reference the row in courses.
Likewise, a student may want to withdraw from school this semester. They try to remove their record:
DELETE FROM students WHERE student_id = 9877;
This is blocked, because the student is still enrolled in the photography class.
The enrollments class is a bridging table (I call these intersection tables, but there's no official terminology for these types of tables). It is basically a pair of foreign key columns, which reference the respective tables courses and students.
The foreign key constraints in enrollments require that each of the referenced rows in the other two tables exist. You can't delete either the courses row or the students row while there's an enrollment that references it.
The way to handle this is to delete the dependent row (the one that has the foreign key constraint) before you delete the referenced row.
The optional ON DELETE CASCADE syntax makes a foreign key constraint handle this automatically. That is, deleting a row in courses would automatically delete any rows that reference the course. If you don't use this option, then trying to delete the course returns an error.

Foreign keys in mysql

I have a doubt about the way of relating some tables. I have these tables:
User table: username (primary key)
Team table: team_name(primary key), username (foreign key references User(username))
With this relationship, I get that an user can have more than one team.
Group table: group_name (primary key)
I want that a group can have many teams, but these teams have to be of different users, so two teams of a user cannot be in the same group.
I have thought to do a relationship with the three tables of this way:
Group_teams table: (group_name, username, team_name). This table would have a composite primary key (group_name and username), in this way I would be sure that an user cannot has more than one team in a same group.
In addition, I think that I should create a composite foreign key references User(username) and Team (team_name) to be able to control that the team of a user exists. Finally, I should create another foreign key references Group (group_name) to control that a group exists.
I'm not sure that it would be of this way because I have errors when I try to do it. Could yo help me and tell me your opinions?
If a user can be on (at most) only one team, then you have a 0/1 - many relationship.
The easiest approach is to have TeamId in the Users table. This would be a foreign key reference to Teams.
There is no need for a third table to represent this relationship.
There's no need to reproduce the username field in the Group_teams table, just have group_name & team_name.
Create a trigger on the Group_teams table to fire before a new row is inserted, checking for more other teams with the same username.
Have a look at the question "How do you check constraints from another table when entering a row into a table?", specifically this answer from Jim V describing such a setup.

Retrieve data in mysql with foreign key relationships over multiple tables?

I have read everything I could find on the web regarding JOIN and foreign key relationships, but can not seem to get my head around a solution to solve my problem.
As you can see in the relationship diagram image my CUSTOMER table have a foreign key relation with TASK_IN table.
TASK_IN table have a foreign key relation with TASK_ID table.
I want to retrieve all data from the TASK_ID table. Can this be done via the CUSTOMER and TASK_IN table foreign key relation - if yes, how would the SQL query look (PHP)?
SELECT * FROM task_id AS taskid INNER JOIN task_in AS taskin ON taskid.id = taskin.id INNER JOIN customer AS cust ON taskin.id = cust.id WHERE id = YOUR_VALUE_HERE
EDIT:
this is just basic sql syntax, you can read more here.

mysql multiple foreign key vs inner join

Is there any sense in using two foreign key to the same parent table, to avoid inner join?
table: user_profile
id1, userid, username, firstname
table: user_hobby1
id2, userid(fk), hobby, movies
table: user_hobby2
id3, userid(fk), firstname(fk), hobby, movies
I want to select all firstname and hobby from the above table. I am not sure if user_hobby1 or user_hobby2 is the best design in terms of performance? One adds extra foreign key and another requires join.
Query1 :
Select firstname, hobby
from user_hobby2;
Query2 :
Select p.firstname, h.hobby
from
user_profile p
inner join user_hobby1 h on u.userid=h.userid;
Copying the value of an attribute from the user table into the hobby table isn't a "foreign key", that's redundancy.
Our performance objectives are not usually met with an approach of avoiding JOIN operations, which are a normal part of how relational databases operate.
I'd go with the normalized design as a first cut. Each attribute should be dependent on the key, the whole key, and nothing but the key. The "firstname" attribute is dependent on the id of the user, not the hobby.
Sometimes, we do gain performance benefits by introducing redundancy into the database. We have to do that in a controlled way, and make sure that we don't get update anomalies. (Consider what changes we want to apply if the value of "firstname" attribute is updated... do we make that change to the user table, the user_hobby table, or both.
Likely, "firstname" is not unique in the user table, so we definitely don't want a foreign key referencing that column; we want foreign keys that reference the user table to reference the PRIMARY KEY of the table.
There's no point in having two foreign keys defined between user_hobby and user, if a user_hobby is related to exactly one user. We only need one foreign key... we just store the id from the user table in the user_hobby table.
if you have two FK in user_hobby2 then you can only ensure that userid and username exist in user_profile, but you have no way to ensure which userid goes with a given username.
if you make (userid, username) a composite FK, then you'll guarantee the consistency of each tuple, but composite FK are generally more complicate to deal with. Depending on the behavior for update and delete cascades I've seen mysql triggering them both and refusing to delete from the parent.
Besides... what's the point of keeping that composite FK? It will only help you when you update or delete from user_profile, but won't help you copy the data when you insert new users or new hobbies for a user.
The join you are trying to avoid is very cheap. Just go with the first approach. It's easier to maintain and will help you keep your data consistent and normalized.