Can we use PK of M2M relation for another M2M table? - mysql

I have some tables like this :
batches(id, name)
terms(id, name)
subjects(id, name)
Batches is having many-to-many relation with Terms in a table called batches_x_terms.
I wanted to create a table to assign Subjects to many terms and those subjects be traceable from Batches too, so I thought of creating a table like this :
batches_x_terms_x_subjects(id, batch_id, term_id, subject_id)
But upon further thinking I concluded that I will have lots of rows in this table for less data and data redundancy will be there too.
So I want to know if I can use M2M table's PK as a FK in M2M relation between :
'batches_x_terms' and 'subjects'
Update 1:
Batches table is having another column 'year'
Batches will have same batches from different years, ex
'Science', 2010
'Science', 2011
Now, suppose every Batch is having 4 terms(semesters) and in each term they have different subjects but some subjects are common between these 2 batches, right?
If I follow 'batches_x_terms' and 'batches_x_subjects' then I won't be able to figure out which subject is taught to which batch in a specific term. I need to classify my data like this :
Batches have how many terms?
Which subjects are assigned to which Batch in a specific term.
Same subjects can be assigned to another Batch in some other term.
Moreover, I have a constraint that I can't assign a different Term ID to every Batch, for a single semester every Batch will have a common Term ID.
I hope this much detail is useful.

Declare a column set whose subrow value is unique but doesn't contain any smaller column set whose subrow value is unique as UNIQUE NOT NULL. (I'll limit myself to when NOT NULL is appropriate.) You can define one such set per table as PRIMARY KEY instead. (That's equivalent as a constraint to UNIQUE NOT NULL.)
When a column set subrow value must appear in another table as a subrow value for a unique column set declare a FOREIGN KEY. If the unique column set isn't already declared UNIQUE or PK, do so.
Not only "can" you declare a PK, UNIQUE and/or FK per above, you should declare every one that could be. (Some DBMSs will prevent you from declaring FK cycles though.)

Related

MySQL : One to One Relationship Tables Merging

I am trying to simplify an application's database. In that database I have two tables let's say Patient and MedicalRecord. I know that two tables are said to be in One-to-One relationship iff that any given row from Table-A can have at most one row ine Table-B(It means there can be zero matchings).
But in my case, it is not at most, it is exactly. i.e., Every row in Patient should have exactly one row in MedicalRecord(no patient exist without a medical record).
Patient table has all personal details of the patient with his id as PK.
MedicalRecord talbe has details like his blood-group, haemoglobin, bp etc with his id as both PK and FK to the Patient.
My Question is, can I merge those two tables and create one table like,
PatientDetails : personal_details and blood-group, haemoglobin, bp etc
"bp" = "Blood pressure"? Then you must not combine the tables. Instead, it is 1:many -- each patient can have many sets of readings. It is very important to record and plot trends in the readings.
Put only truly constant values in the Patient -- name, birthdate (not age; compute that), sex, race (some races are more prone to certain diseases than others), not height/weight. Etc.
Sure, a patient may have a name change (marriage, legal action, etc), but that is an exception that does not affect the schema design, except to force you to use patient_id, not patient_name as a unique key.
Every patient must have a MedicalRecord? That is "business logic"; test it in the application; do not depend (in this case) on anything in the Database.
Both tables would have patient_id. Patients would have it as the PRIMARY KEY; MedicalRecord would haveINDEXed`. That's all it takes to have 1:many.
In situations where the tables are really 1:1 (optionally 1:0/1), I do recommend merging the table. (There are exceptions.)
If two tables have the same set of subrow values for a shared set of columns that is a superkey in both (SQL PRIMARY KEY or UNIQUE) then you can replace the two tables by their natural join. ("Natural join" is probably what you mean by "merge" but that is not a defined technical term.) Each original table will equal the projection of the join on that original's columns.
(1:1 means total on both sides, it does not mean 1:0-or-1, although most writing about cardinalities is sloppy & unclear.)

Adding an auto increment sql script

I have a child table named case_parties, that consists of the name and address of each plaintiff and defendant to court cases.
The table columns include:
case_id, which is a foreign key to the parent table
party_type, which has coded field values of either 1 or 2 (1 indicating a plaintiff and 2 indicating a defendant). The caveat is that there is not always just 1 plaintiff and 1 defendant in every court case. Often, there are multiple plaintiffs and or multiple defendants in a single case. There can be anywhere from 1 to 1,000 + plaintiffs and or defendants on any given case. I created a new column, lets call it party_id and SET it with a CONCAT on the case_id and party_type columns. Therefore, matching rows in this column include either all the plaintiffs or all the defendants to a given case_id.
To create a simple unique key for each row, I want to run a script that adds an auto generated incremental number or letter to the end of the matching party_id field. For example, if there are 4 plaintiffs in the same court case, there are now 4 columns with matching party_id field values, with the last character being 1, representing the party is a plaintiff;
I want to add an increment on so each column is unique and the last two digits of the 4 rows would reflect something like this: "1A", "1B", "1C", "1D" or "1-1", "1-2", "1-3", "1-4",...etc. I'm thinking adding incremental numbers might be easier than adding incremental letters. No other column values individually or collectively make for an efficient composite index in this case. I'm seeking assistance with auto incrementing the matching column values and would greatly appreciate any assistance. Thank you.
I would suggest creating a separate table to represent the defendant/plaintiffs and have a type column in there. Then have a primary key on that table with a regular auto-increment.
You can then use that as your ID in the case_parties table (a foreign key) and it will address your issue with uniquely identifying each one.

MySQL: Where should I place the foreign key?

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.

Do SQL tables benefit or need to have a unique ID column?

In my experience almost all tables have a field called Id that is a unique primary key and indexed. My question is if I'm not using this value anywhere and will never need this value what is the benefit of having it.
Here is my problem:
The database has these many-many relationship tables (often called map tables) that link two other tables together by their unique Ids.
ex rows:
Id= 1 MachineId= 1 UserId= 2
Id= 2 MachineId= 1 UserId= 3
The way the code stands today when it updates this table it removes all Users of a machine and then proceeds to add all of the current users back. This is how they chose to remove old entries. The problem is this inflates the Id column unnecessarily because you remove/add for every user even if nothings changed. This happens by default every 90mins.
One solution to this is to fix the code to do things the right way. Another solution is to just remove the Id field altogether. Since we don't link to this table somewhere else and we don't use the Id value in code anywhere (we don't even pull it from the DB) why do we need it?
So back to my original question. Is the Id field needed for something else? Or does it provide some benefit that I would lose that I may want?
No, it's not needed, and especially for those many-to-many relationships, it is perfectly acceptible to just not have them.
Those ids are especially useful if you have foreign key relations to that table, but even then, you can have foreign keys that consist of a unique combination of multiple columns, so even for foreign keys you don't strictly need them, although it is very much recommended to use single value keys for this purpose.
The added benefit of having a key you don't need, is that you don't need to add it, once you are going to need it. Hardly an excuse. :)
In case you want to google more info:
Those many to many tables are often called a 'junction table' or 'cross-reference table'.
A 'meaningless' unique ID, often auto-numbered, is also called a 'surrogate key'
A key (including primary keys and foreign keys) that consists of multiple fields, is called a 'compound key'. 'Composite key' is often used as a synonym, although Wikipedia has a slightly different definition.
Technically, you don't NEED to have a unique id, but there are far too many situations where not having one will really screw you up. e.g. Consider an address book. You might assume that "firstname, lastname, address" is enough to identify someone, but consider "John Smith, 123 Main Street" and "John Smith, 123 Main Street" (John Junior). Obvious solution: add a "Jr." field, or add more to the key and keep hoping you won't ever get a duplicate.... or you just add an auto_increment ID field and be done with it. doesn't matter what other fields are duplicates across records, you KNOW the id field will be unique.
You can easily make a unique composite key if you'd like, but then if you need to set up a foreign key relationship, you'd have to duplicate ALL of those keys' fields in the foreign table.
e.g.
table A (
p, q, r, s t -> char
primary key (p, q, r, s, t)
)
table B (
h, i, j, k -> whatever
p, q, r, s, t -> char
foreign key (p, q, r, s, t) -> A (p, q, r, s, t)
)
Now you've got your pqrst fields in two tables, and have to write them out, IN FULL, for every join operation. Whereas, if you had a simple single ID field:
table A (
id -> primary key int
p, q, r, s ,t
)
table B (
h, i, j, k -> hwatever
a_id -> int
foreign key (a_id) -> A (id)
)
one simple int field carried between the two tables, v.s. n fields for every field in the composite key.
Short answer: In this case, you described in your question, the ID column is not necessary, you can drop it if you will and add a PK/Unique to the table which is built up using the IDs from the linked tables.
Long answer (with my personal opinion): The ID column was used to speed up queries which are using lots of joins (comparing an integer is mostly faster than comparing long strings), and to moderate the size of link tables and foreign key columns. Another usage is to add a unique identifier to those tables which laks simple real life identifiers (like log tables).
In some cases the ID column is just added because all tables contains an ID column.
You always have to consider that the ID column has any meaning or is it really necessary: if you have character codes (using only ASCII characters) with less than 4 charactes length, the code will be smaller than the INT ID column (INT is stored on 4 bytes, bigint on 8 bytes).
Another thing: Always add the name of the entity to the ID column (such as PersonID, InvoiceID) to make the queries and schema more readable. In my opinion, a column's name always should represent what it stores, the name ID is just not describes the value stored in the column, when PersonID does. Furthermore, you can (and should) use the same name in foreign keys.
In most cases in our time with the current hardwares, the ID columns are mostly complicates the databases (you always have to join several tables to get the business/natural key). Furthermore the ID has no meaning for the business. You can always consider to leave the ID column and use a natural key as primary key. (You could leave the ID column, when you have an ID as a PK and one more column defined as unique not null: for example: A table contains invoices: the PK could be the InvoiceNumber which is on the paper based invoice, rather than the ID, but if the database is responsible to generate that number, you have to use a sequence based column.)
The ID (or any machine generated identifier) is useful when you don't have simple natural keys to use (or you have natural keys, but they are too wide or the have to build up using several other columns), or the natural key us mutable, you have to have some king of uniq identifier (car's license plate number is one example).

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