MySQL: Where should I place the foreign key? - mysql

I have a doubt. Please read the below example carefully.
There is an Income type called Other Income
Every single Other Income May or May Not be subjected to VAT.
One Other Income can have only one VAT, if it has any.
As you can read in above points, the relation between the Other Income and VAT is One to One/ None.
Now see the below image.
We wanted the VAT table to contain the Other_Income reference, so the idVat is in Other_Income table.. In case you are wondering why there is a separate VAT table, that is because lot of other types of fees are subjected to VAT too.
However imagine due to some reason someone wanted the Other_Income table to contain the VAT reference. In this case, If you are using MySQL Work bench or GUI tool to build the diagram, the 1 in relationship line will be presented in the side of Other_Income table and the 0..1 will be presented in the side of VAT table.
However, whatever it is, it has the connection One to One/ None. So, there is no connection between Relationship and the location of the foreign key? In other words, there is no rule something like You must put the foreign key to X table of the relationship. Other table is prohibited. ?
As far as I can see and know there is no such rule, you can put the foreign key to any table in the relationship, it is just your preference and decision to make the things "work". However I would like to clear my doubt.
Update
The above is just an example to explain the question with more sense. Therefor, please do not make your answer depend on the "exact" above example.

The foreign key can be null. In some cases, you just don't know what the value of the key is.
You can have a look at this link.
There is a link between relationship and location of the foreign key. If you just put the value of the foreign key to the table where the foreign key is not defined, it would be just a normal value, without all the benefits which having keys provides.

There is a foreign key (FK) from one table column referencing another when the value in the column in the referencing table always appears in the column of the referenced table and the referenced column is unique in the referenced table. (It is declared UNIQUE NOT NULL or PRIMARY KEY there.) Also, in SQL a referencing column can be NULL.
Since the referenced column is unique in the referenced table, a row in the referencing table either IS NOT NULL and matches exactly one row in the referenced table or IS NULL. And many rows in the referencing table might refer to the same row in the referenced table. But some rows in the referenced table might not be referenced by any row in the referencing table. So a NOT NULL referencing row goes to 1 referenced row and a nullable one to 0-or-1 referenced row. And a row is referenced by 0-or-many referencing rows. So a foreign key means a 0-or-many-to-(0-or-)1 situation.
Your 1/2/3 just says that there is a nullable FK from Other_Income to VAT. Ie 0-or-many-to-0-or-1. That does not justify having a 1 instead of the many and it doesn't justify having a FK from VAT to Other_Income. Ie it is not true that 1/2/3 means "the relation between the Other Income and VAT is One to One/ None".
If it happens that there are other constraints then you have not said so yet. Eg that there is also a FK in VAT referencing Other_Income. In that particular case each Other_Income has its own VAT if it has one. (And it has to also be that a VAT has its own Other_Income if it has one.) But in that case if a VAT always has a matching Other_Income we have the Other_Income-VAT 1:0-or-1 and if a VAT doesn't always have an Other_Income and so is nullable then we have Other_Income-VAT 0-or-1:0-or-1. (I now use ":" because there is a "to" in both directions.)
The only time you get to pick where to put a FK is when you have 1:1 and you leave one FK out. Ironically in the 1:1 case you could just put all the info into one table without FKs and that is the symmetric and non-redundant design rather than two tables. In the 0-or-1:0-or-1 case if we wanted to avoid using NULL then we would have no FKs in either table and add a third table with the two columns, each a FK, each a PK, enumerating paired values.

The Other Income can have a VAT. So that table must be given a column idVAT. For every record there will either be an entry or NULL.
So you have an {0-n}:{0-1} relation. Every VAT ("reduced rate", "normal rate", etc.) can be assigned to n Other Incomes (with n being zero or any number). And every Other Income can have 0 or 1 VAT.
In order not to be able to enter a non-existent idVAT in Other Incomes, you make this a foreign key to the VAT table.
If you want a real {1}:{0:1} relation between two tables, e.g. the VAT table doesn't contain the VAT level ("reduced rate", "normal rate", etc.), but an amount of money, then things get slightly more complicated.
Usually you wouldn't make this two tables then, but just one (the VAT amount would be a nullable column in Other Incomes). If you really need two tables, then you would give the VAT table the idOther_Income, because each VAT entry refers to one Other Income. So this time it is vice versa, but still you would use a foreign key to ensure data integrity. This time from VAT to Other Income, of course. You would also give VAT.idOther_Income a unique constraint, so there can only be one VAT per Other Income.

I hope I have understand you question correctly.
It seams you have different Fee tables(like Other-Income ...). Any row inside Fee tables may have a VAT record.
Conditions are:
A VAT won't happen if there is no fee (correct me if I am wrong).
A Fee needs to keep trace of its VAT(if happens).
A VAT needs to keep trace of its Fee (must happen).
A Fee can have only one VAT.
I will suggest to have a base table called Fee_Base (or simply Fee) as the base for other fees. This base table will contain shared properties of other fees like date of happen, amount etc.
Having Fee_Base foreign key being mandatory inside VAT will satisfy the 1,2 and 3 conditions.
Assigning Fee_Base foreign key being Unique will satisfy number 4.
Simply Fee_Base foreign is the primary key of VAT table.

Related

Can A Foreign Key Be Used More than Once?

Apologies for the newbie question.
The primary key of a table, such as Holiday, would be something like Holiday_ID. Holiday reference a get-away ticket that you can buy to go on a type of holiday, based on the ticket you buy.
Suppose I used Holiday_ID in a composite entity with Customer_ID to identify an instance of Holiday associated with customer, for whatever purpose.
However, suppose I also want to keep track of other information related to this instace: how much has the customer paid for the ticket, how much has the customer yet to pay for the ticket
I have two options:
a) I can create another composite entity. However, I am not sure if I can do that because I am not sure if you can use a particualr foreign key more than once
b) I can create a composite/associate entity, however, I am not sure if you can create a composite entity with more than two foreign keys?
To answer the technical parts of your question, once you create a composite unique or primary key, ONLY ONE record in the table can have the same values in the set of fields defined in that key. SO, no, you cannot reuse the holidayId key WITH THE SAME customer. You can use it with another, different customer if you wish.
Second, there is no limit to the number of attributes that can be included in a Unique or primary key. If you need, and if it's appropriate and conforms to the rules of normalization, the key can include all the attributes of the table.
Third, to answer your question below, Any column, or set of columns in a table can be defined as a Foreign Key, as long as it is also the primary key or unique key of some table in the database. And there can be any number of FKs defined in a table, they can even overlap. (you can have HolidayId as a FK, and also have HolidayID and CustomerId as a composite FK) the only restriction is that the FK must reference a Primary or Unique Key of some table in the database.(It can also be the same table the FK is in as well, as when you add a supervisorId to an employee Table that is a FK to the EMployeeId of the same employee table)
This example illustrates one of the problems of using surrogate keys without also using a natural key. to wit, what, exactly is a "Holiday"? Is Christmas 2016 the same "Holiday" as Christmas 2015? Is Christmas in Aruba the same holiday as Christmas in Hawaii?
and then, about the composite table to identify associations of customer with Holiday, is it the same association if the customer goes to Aruba on Christmas the next year, or a different instance? What does the row in the table represent if the customer wants 5 tickets?
The first thing that should be done in database design is a logical design which defines, as clearly and unambiguously as possible, in business terms, the meanings of the entities for each table in the database.

Is it necessary to bring the primary key of non repeating table while normalizing the database from UNF to 1NF

My UNF is
database(
manager_id,
manager_name,
{supplier_id,
supplier_name,
{order_id,
order_quantity}}
{purchase_id,
purchase_date}
Here manager_name, supplier_id, order_id and purchase_id are primary key.
During normalization there will be 1 table called purchase. Is it necessary to make manager_name as a foreign key?
How can I normalize these database?
This is a part of my college project on database. Normalization is really confusing.
First consider splitting things out by things that naturally go together. In this case you have manager information, supplier information, order information and purchase information. I personally would want to know the difference between an order and a purchase because that is not clear to me.
So you have at least four tables for those separate pieces of information (although depending on the other fields you might need, suppliers and managers could be in the same table with an additional field such as person_type to distinguish them, in this case you would want a lookup table to grab the valid person type values from). Then you need to see how these things relate to each other. Are they in a one to one relationship or a one-to many or a many to many relationship? In a one-to one relationship, you need the FK to also have a unique constraint of index to maintain the uniqueness. In a many to many you will need an additional junction table that contains both ids.
Otherwise in the simplest case the child table of purchase would have FKs to the manager, supplier. and order tables.
Manager name should under no circumstances be a primary key. Many people have the same name. Use Manager ID as the key because it is unique where name is not. In general I prefer to separate out the names into First, middle and last so that you can sort on last name easily. However in some cultures this doesn't work so well.

Mysql composite primary key

I want to have a lookup table that links two of the same things to eachother. Say I have a 'Person' table and I want to lookup the relationship between two people. I'll have column one of the lookup be 'PersonId1' and column two be 'PersonId2' and the third column be 'Relationship'. Since the relationship goes both ways I don't need to have duplicate records with the PlayerId's switched. Is there any way to make mysql enforce uniqueness on PlayerId1 and PlayerId2 combinations regardless of which order they're in?
Does that make sense?
Short answer: No.
Longer answer: You could set up a trigger to swap the order of the two person ids if the second were smaller than the first, then write them, and use a composite key.
Even longer answer: Not all interpersonal relationships are commutative (not all relationships go both ways). What about the "Employee" or "Mother" relationships? Even the "Friend" relationship, which is presumably peer-to-peer, might be better represented if you had separate rows saying A is B's Friend and B is A's Friend. So maybe you want a three-field composite key on this table.
You mean you want to have a unique row record from PersonID1 and PersonID2 Column (regardless of the Relationship column)? If that so, you may use the Composite key (Multi column key).
Here's an example:
CREATE TABLE Person (
PersonId1 INT,
PersonId2 INT,
PRIMARY KEY (PersonId1, PersonId2)
)
+1 for composite pk. To prevent duplicate combinations, an extra varchar column with for example personid1+personid2 with a unique constraint on it may be a solution...
See also: person data model example

To make PK on unique combination of columns or add a numeric rowID

This is more of a design problem then a programming one.
I have a table where I store details about retail products:
Name Barcode BarcodeFormat etc...
----------------------------------------
(Name, Barcode, BarcodeFormat) are three columns will uniquely identify a record in the table (Candidate Key). However, I have other tables that need a FK on this one. So I introduced an auto_increment column itemId and made that the PK.
My question is - should I have the PK as (itemId, Name, Barcode, BarcodeFormat) or would it be better to have PK(itemId) and UNIQUE(Name, Barcode, BarcodeFormat).
My primary concern is performance in terms of INSERT and SELECT operations but comments on size are also welcome.
I'm using an innodb table with mysql
Definitely: PK(itemId) and UNIQUE(Name, Barcode, BarcodeFormat).
You don't want the hassle of using a multi-part key for all your joins etc
You may one day have rows without barcode values which then won't be unique, so you don't want uniqueness hard-wired into your model (you can easily drop the unique without breaking any relationships etc)
The constraint on uniqueness is a business-level issue, not a database entity one: You'll always need a key, but you may not always need the business rule of uniqueness
Unless you have millions of products, or very high throughput requirements it won't make much difference in terms of performance.
My preference is to have a surrogate PK (i.e. the auto increment column, your second option of PK(itemId) and UNIQUE(Name, Barcode, BarcodeFormat) ) because this is easier to manage if business keys change.
You have two candidate keys. We call the three-column compound key the 'natural key' and the auto_increment column (in this case) the 'surrogate key'. Both require unique constraints ('unique' in lower case to denote logical) at the database level.
Optionally, one candidate key may be designated 'primary'. The choice of which key (if any) should get this designation is arbitrary. Beware of anyone giving you definitive advice on this matter!
If you already add an itemId then you should use that as PK and have the other three columns with a UNIQUE.
If you don't have an itemId then you could use the other columns as the PK, but it may become difficult to keep it everywhere. In this case it is not great, because the product should have an id since it is an entity, but if it where just a relationship, then it would be acceptable not to have an id column.

In a One to One relationship should i drop one of the table's id column?

I have the following 2 tables in MySQL:
Customer(Id, Firstname, Lastname...)
Bonus(Id, CustomerId, Value, ...)
The relation is One-To-One, every customer has only one bonus.(the CustomerId is unique in the Bonus Table)
Q: Should I drop the Id column of the Bonus table?
(I want to know why or why not)
I would remove the Bonus.Id coulmn and make Bonus.CustomerId the PK. Doing this will remove the need to have a unique constraint on the Bonus.CustomerId column, since it will now be a PK. Anyone looking at the table will see the one-to-one more clearly without the Bonus.Id coulmn. You won't need an index on Bonus.CustomerId, the PK index will be all you need, so less disk space and memory cache wasted. Also, if you ever need a FK to the Bonus table, you you would use the CustomerId value (the new PK), which can be used to get back to Customer or Bonus tables, not just Bonus.
I assume it isn't actually a true one-to-one because you could presumably have a Customer without a bonus row. SQL-style foreign key constraints are always optional on the referencing side of any relationship.
I agree the Bonus.Id column appears to be completely redundant.
if it's ono-to-one, why is there any extra table? you could instead put "bonusvalue" into your customer table.
(else: yes, you can drop the id of the bonus-table, the customer-id is the primary key and the "id" is completely redundant)