InnoDB relationships: one-way or two-way? - mysql

I've decided for the first time to switch to InnoDB and experiment with foreign keys and other InnoDB features.
When creating relationships, should I declare them only on 1 table? Or both tables?
For example, for each cases below, where and how would you declare the relationships?
1 User has many widgets
widget belongs to 1 user (is that same as above?)
1 user has 1 widget
user [many-to-many] widgets
many users share 1 widget
Those are just some random examples, I'm just trying to understand which directions relationships should be declared.
Also, on the same note, which direction do "ON CASCADE" stuff work?
Thanks

1 User has many widgets
Assuming a widget is exclusive to one user (because you have a seperate point for many to many): user_id on table widget that references the primary key on user
widget belongs to 1 user
see above.
1 user has 1 widget
widget_id in user table that references primary key on widget table, with unique index on widget_id, or the other way around, doesn't really matter. If it is a 1-to-1 and not a 0 or 1-to-1 relationship, you should consider putting widget and user in one table.
user [many-to-many] widgets
Introduce a third table, user_widget, with 2 fields user_id and widget_id referencing the corresponding primary keys in user and widget table.
many users share 1 widget
same as "1 user has 1 widget", but without a unique index on the widget_id
The ON CASCADE option works from parent (primary key) to child (foreign key/reference). So if you have a ON DELETE CASCADE in your first scenario (1 User has many widgets), delete a user deletes all his widgets, but deleting all widgets doesn't delete the user.

Related

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.

Is this database design circular?

I am working on a group management page with a variable number of tabs from which the admin(s) of each group on the site can choose for their page. Admins shall also be able to create group member roles, assign privileges on the tabs to those roles, and assign roles to the members. Any member can also belong to one or more groups.
I have sketched out some tables for the database to this. Here are the three of interest:
groups
----------------
GroupID <- PRIMARY KEY
GroupName
GroupDescription
group_member_records
--------------------
GroupMemberRecordID <- PRIMARY KEY
GroupID <- FOREIGN KEY: references groups.GroupID
GroupMemberID <-FOREIGN KEY: references group_members.GroupMemberID
GroupMemberRoleID <- FOREIGN KEY: references group_member_roles.GroupMemberRoleID
group_member_roles
-----------------------
GroupMemberRoleID <- PRIMARY KEY
GroupID <- FOREIGN KEY: references groups.GroupID
GroupMemberRoleName
// NOTE: GroupID,GroupMemberRoleName UNIQUE
I initially decided to just give group_members a GroupMemberRoleID foreign key, but the problem with that is that it would be possible for a member to belong to multiple groups, and have a group member role, and that group member role would be different for at least two of the groups of which that member belongs to! Thus, I moved the GroupMemberRoleID foreign key to group_member_records.
Before I finally implement that table that records all the tab privileges for the groups, I would like to know a couple of things:
Is there any risk of circular reference? I have seen closely related question answered here, but am unsure what they mean by:
This is not a circular reference.
It would be if emails would have a strong integrity relationship to
invitations and invitations an independent strong integrity
relationship back to emails (for example).
(my bold on what was unclear to me)
Is this, at all, bad design or bad practice?

Adding column on specific row location

Its just a quick question :
I have user table and it has fields name, address and books_bought. books_bought is foreign key and its value is some PK from other table. Now after 1st insert, I will fill out all of this fields , but after second INSERT I want only to add a additional books_bought, so that am creating array of books_bought values?
You're doing it the wrong way around - this is a one-to-many relationship i.e. many books bought to one user. You need to have the foreign key on the many side of the relationship, so instead of having a foreign key to books_bought on the users table, add a foreign key to users on the books_bought table.
If you have a books table and a users table, then this is a many-to-many relationship and you will need a link table to go between them to hold the foreign keys.
You should not have more than one book in the books_bought cell because it will violate the atomicity constraint fo the database tables. You have to have a separate entry for each book_bought. This would cause a lot of redundant information as name, address would be repeated for each book bought by a specific person.
To solve this, you have to split the table into something like this:
R1(primary_key , name , address) and R2(foreign_key , books_bought)
Here foreign_key refers to primary_key of R1

How to handle data storage for each user MySQL

suppose I have a table with users in my website. Now if I want to make a system where users can upload a single image each, it would be something like this:
But if I want to make a system where users can upload an unlimited number of images, how would I achieve that? Would I need to create a column for each image uploaded per user? But in that case, wouldn't be fields unused? Example:
Also, if I wanted to make albumns for the photos how would I handle that? Thanks!
The best way of handling this would be to have a separate table for images, but with a userID which is a foreign key for your user table.
Assuming no two users would use the same image (which would be a different situation),
You have your user table just as you have (the first one), but with only the id and user.
Your second table would look something like this, where imageID is the primary key, and UserID is a foreign key for ID off of your user table
imageID UserID
1 1
2 1
3 1
4 2
5 2
If you want albums, you could just create another table with albumID as a primary key, and imageID as a foreign key to this image table. You can also include UserID on that table and create a composite primary key if you want a many-to-many relationship. This way albums are still associated with users, but you could have images appear in multiple albums

Storing key value where key repeats and using primary keys

I am in a situation where i have to store key -> value pairs in a table which signifies users who have voted certain products.
UserId ProductID
1 2345
1 1786
6 657
2 1254
1 2187
As you can see that userId keeps on repeating and so can productId. I wanted to know what can be the best way to represent this data. Also is there a necessity of using primary key in here. I've searched a lot but am not able to find the exact specification about my problem. Any help would be appreciated. Thank you.
If you want to enforce that a given user can vote for a given product at most once, create a unique constraint over both columns:
ALTER TABLE mytable ADD UNIQUE INDEX (UserId, ProductID);
Although you can use these two columns together as a key, your app code is often simpler if you define a separate, typically auto increment, key column, but the decision to do this depends on which app code language/library you use.
If you have any tables that hold a foreign key reference to this table, and you intend to use referential integrity, those tables and the SQL used to define the relationship will also be simpler if you create a separate key column - you just end up carting multiple columns around instead of just one.