i have a question about the 1 normal form and will explain it by an example.
lets imagine that we have a set of students that are working on a set of projects, but not necessarily only one, but more than one (many to many relation). we have a table where the information's of the students are recorded, and one for the projects. but we need to link them together. but since the 1NF says redundancy and only value per tuple, how would you do it?
both fields are primary keys here
illustation 1:
student_ID project_ID
1 7
2 7,1
3 4,1,9
4 1,3
5 1
illustration 2:
student_ID project_ID
1 7
2 1
2 7
3 4
3 1
3 9
4 1
4 3
5 1
Illustration 1: I know that if this would be a result of a table, this would violate the 1NF becuase one than one value per tuple.
Ilustration 2: since they are primary keys they are not allowed to be duplicated, even if i remove the primary key from the student_ID i still would be redundant.
How can i fix this issue?
thanks in advance :)
The primary key of this table will be a composite of the two fields. They must both together be unique. Both fields are foreign keys to their respective tables and they will be unique in their respective tables.
What you have here is basically a junction table, and your second illustration shows the correct way to normalize it.
Note that, as is typical for junction tables, the primary key for your table will consist of both of the columns together. Together, each unique combination of values in these columns specifies a distinct student–project pairing.
Edit: In MySQL, you would define this table e.g. as:
CREATE TABLE student_projects (
student_id INTEGER NOT NULL,
project_id INTEGER NOT NULL,
PRIMARY KEY (student_id, project_id)
)
To enforce relational consistency, you may also want to add explicit foreign key constraints to each of the columns.
Related
I have an extreamly simple idea: table that keeps user "achievements". And it is as simple as that:
user_id | achievement_id
1 | 1
1 | 2
1 | 5
2 | 2
2 | 3
All what I need is user id, and id of achievement if he already got it. All what I need to SELECT is SELECT achievement_id WHERE user_id=x. So no need for an artificial autoincrement column that I'll never use or know what it contains. But setting an primary key is required, so the question is - is it good idea to make such 2-column table and set both columns as multi-column primary key? I already have a set of 3-columns table where 2 are primary key, because it is logic... Well, logic for me, but for the database?
These types of tables are common in cases of n-n relationships, multivalued attributes, and weak entities. It varies a lot from its modeling, but yes, it is a good solution for some cases. the primary key is usually the relation of the columns. In your case it would be user_id and achievement_id.
Yes since the rule for such a set of n-keys is: "I only want one kind of record which has this set (a,b) of keys".
-> therefore you won't be able to add twice "Mario, achievement1".
Primary key will be then (PlayerID, AchievementID).
If you want to add some informations about this achievement (for example, when the player got the achievement), simply do such as: (PlayerID, AchievementID, Date) with PlayerID, AchievementID as primary key.
I hope this will help you.
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.
I wasn't sure how to explain this in the title, but what I have is a table like this:
user_id | subscription_id
6 12
6 10
12 6
4 12
Each user can subscribe to all other users, but is it possible to prevent a user from subscribing to another user twice through a INSERT query?
As my subscription_id is not unique, this happens:
user_id | subscription_id
6 12
6 12
And I want to avoid that. As far as I know INSERT IGNORE, INSERT UPDATE and ON DUPLICATE only works with unique keys.
You need to set up your database table to have a composite primary key for user_id AND subscription_id
That way each row has to be unique across both the columns.
See: How to properly create composite primary keys - MYSQL
The only reliable and easy way to make sure that a tuple cannot occur more than once inside a single table is either:
Use a spanning unique key
Use a spanning primary key
Maybe triggers
The first two are roughly the same, but unique keys treat null values as distinct as well, so that might not work for you.
ALTER TABLE user_subscriptions ADD PRIMARY(user_id, subscription_id);
i have two tables, one 'master' and one 'child' table.
Each table has a field named 'ProductNo', which is defined as PRIMARY KEY and UNIQUE.
Is it possible to define the field 'ProductNo' in the table 'child' and the same field in table 'master' as PRIMARY + UNIQUE together?
master:
ID | ProductNo
child:
ID | MasterID (FK on master.ID) | ProductNo
Relation >> 1 (master) : n (child)
example data:
master:
1 | 1234
2 | 4567
child:
100 | 1 | 3333
101 | 1 | 4444
102 | 2 | 5555
103 | 1 | 1234 <----- NOT ALLOWED! PRODUCT NO ALREADY EXISTING IN TABLE `MASTER`
104 | 2 | 1234 <----- NOT ALLOWED! PRODUCT NO ALREADY EXISTING IN TABLE `MASTER`
It is needed to check on inserting/updating table 'child' if 'ProductNo' already exists in table 'master'.
How can I define it?
Or am I needed to create a trigger for this?
TIA Matt
no, there is no such thing as composite PKs among tables.
Just for data consistency, if the Ids are the same, you should add a FK from child to the master.
To solve your problem, a trigger with a check like this:
if exists (select 1 from master where prodcutId=new_productId)
would be a good idea
EDIT:
actually the best idea is to have only one table called product with a ID and a masterID field with a relation to itself. The way you have today Im pretty sure that you have a lot of duplicate data and you are stuck with 2 levels on hierarchy.
(Original answer) You can declare a foreign key from master to child, even if that foreign key points to the primary key of child. This would be a one to zero-or-one relationship, and is not that uncommon. A row cannot exist in child without a matching row in master already being inserted, but a row can exist in master without a matching child row. Your inserts therefore need to happen in the order master then child.
(Edited in light of question edit) HOWEVER, in your case, the column you are referring to looks like it should not actually be the primary key of either table, but rather you have a separate primary/foreign key, and the column in question needs to be unique across the two tables, which has become clear now you've edited some sample data into your question. In this case, you'd be best to use a trigger on both tables, to check existence in the other table and prevent the insert/update if the ProductNo already exists.
Just as #DavidM said, it can be done, but it seems you are with some modelling issues. First, if you have a natural primary key ProductNo, why do you define a surrogate ID? The other thing you might consider is to combine these two tables into a single one (as might make sense for most of 1-to-1 cases).
Are you sure you need the two tables?
Keep just one, having productID plus parentID.
Then productID can be a primary key and auto increment, while everything having a parentID other than null (f.keyed to the same table) would be a child item.
You can add a column named ProductNo in child table and add a foreign key reference to the parent table.
I have a table in Access which I'd like to substitute with a query which gathers data from the table and other new tables. The table is used by many queries which look to a primary key (autonumber) in the table, so the new query must have a primary key which is a unique combination of the primary keys of the tables used by the query. What can I do?
--EDIT--
Solution found: Since I want to "merge" tables with a query, and since the pk is an autonumber, I can define the new pk (of the query) by "expanding the numbering": I multiply both pkeys by 2 (because I have two tables) and add or subtract 1 to one of the two (or 1 for the first table and 2 for the second, and so on).
For example:
PK1 = 1,2,3,4,5,6
PK2 = 1,3,4,5,8,9,10 (some records may have been deleted, so the number is skipped)
new PK = (2*PK1, (2*PK2 + 1)) = (2,4,6,8,10,12),(3,7,9,11,17,19,21)
as you can see they will never overlap (no new value of PK2 can be obtained from any value of PK1, because of the "+1") because math says they belong to different vector spaces.
Hope it may help somebody
Use composite key (Multiple-field primary key)