RDBMS best practices - autoid for association table? - mysql

I have two tables, let's say they are called table A and table B. An item from table B can be present in multiple instances of A, and each A can contain multiple Bs so I have a table called a_b which links them together by their primary keys. My question is when I define this association table, should I have a primary key on the association table? Or is it not needed? Just trying to avoid ending up on TDWTF, that's all :)

The primary key would be on the table A PK column and table B PK column in your association table. That way, you ensure you don't get any duplicate rows in your association table by accident.
One of the main purposes of primary keys is to guarantee referential integrity. That is, keep the data in your table clean, with no duplicates. The PK in this case will ensure you never have 2 duplicate rows in the association table.

I think you might want to use a primary key in order to show your intent. If for example you do not want
a, b
a, b
Then a primary key defined on A.a and B.b would make that more clear. If you don't care, but you have a,b and other fields, then adding a surrogate key as your primary key might help in giving you a uniform way to delete a row that you do not want. Otherwise you will have to delete where a=a and b=b and ?? then pick some field value from the row you want deleted. Whereas with a surrogate key you can just pick the row and say delete where mykey = 36 or something...
But really it depends on the business case. Many intersect tables have some kind of date range, or additional fields related to the relationship in addition to the keys of the two tables. Defining a primary key on the existing columns, a new surrogate key, some unique indexes, some constraints, or even having no indexes could all be valid courses of action depending upon your needs.
I would say definitely do whatever makes your intentions the most clear.

Not needed. Both keys should form the primary key of your association table. If you're going to be doing bidirectional navigation, consider adding an index with the keys reversed.

The primary key is needed always.
However, I'd say it depends what should it be. If you are going to use some sort of ORM systems (e.g. Hibernate) then it is best to have a surrogate identifier, while those two foreign keys (pointing to tables A and B) should form a unique index.
Also, if there would ever be a need to reference such a relationship from another table then this surrogate identifier would be really handy.

Related

How do I make a field reference another field which is not a primary key in MySQL?

I know that foreign keys need not reference only primary keys but they can also reference a field that has a unique constraint on it. For my scenario, I am setting up a quiz where for each test, I have a set of questions. My table design is like this
The point is, in my 2nd table where I will put all the answer options, I want the question number field to link to the first table question number. How do I do this? Or is there an alternative to this design?
Thank you
Ideally there should be a question_id primary key column in the test_question table, and you would use this as the foreign key in the test_answer table.
With your composite primary key in the test_question table, you should make a corresponding composite foreign key:
CONSTRAINT FOREIGN KEY (test_id, question_no) REFERENCES test_question (test_id, question_no)
This is in addition to the foreign key just for the test_id column.
Add another table purely for answers, and link them via the question_no field.
A DB table should hold information on one sort of item. Questions and answers are separate sorts of information so should be in separate tables. Adding a separate table also allows changes to questions and answers independently. Additionally, if they are separate, you could add a language field to each table and have a multi-lingual quiz
Short answer:
You can JOIN on any columns or expressions. There is no "requirement" for a FOREIGN KEY, PRIMARY KEY, UNIQUE, or anything else.
Long answer:
However,... For performance (in large tables), some things make a difference.
If you are JOINing to a PK, Unique key, or even an indexed column, the query cold run faster.
Why have a FOREIGN KEY? An FK is two things:
A "constraint" that says that the value must exist in the other table. Also, with things like ON DELETE CASCADE, it can provide actions to take if the indicated row is removed. The constraint requires looking in the other table each time a write occurs (eg INSERT).
An Index. That is, specifying a FK automatically adds an INDEX (if not already present) to make the constraint faster.
Getting the id
Here is the "usual" way to do a pair of inserts, where you need the second to 'point' to the first:
INSERT INTO t1 ... -- with an AUTO_INCREMENT id
grab LAST_INSERT_ID() -- that id
INSERT INTO t2 ... -- and include the id from above
For AUTO_INCREMENT to work it must be the first column of some key. (Note: a PRIMARY KEY is a UNIQUE is a key (aka INDEX).)
Optionally you can specify a FK on the second table to point out the connection between the tables.
And, as spelled out in other answers, a FK could involve more than one column.
Entities and Relations
Sometimes, a set of tables like yours is best 'designed' this way:
Determine the "entities": users, tests, questions, answers
Relations and whether they are 1:1, 1:many, or many:many... Users:test is many-to-many; tests:questions is 1:many (unless you want questions to be shared between tests).
Answers is more complex since each 1 answer depends on the user and question.
1:1 -- rarely practical; may as well merge the tables together.
1:many -- a link (FK?) in one table to the other.
many:many -- need a bridge table with (usually) 2 columns, namely ids linking to the two tables.

In MySQL, if has many-to-many table, should i create auto-incr column as PK or use multi-column unique as PK? and Why?

for exmaple, has course relationship table, student id and course id is multi-unique, if i create this relationship table, should i use auto-incr column as PK, or use student id and course id as multi-PK ?
Some people add auto-increment column as PK to just every table.
But I believe it is good to have a multi-column-PK in the case where the table is a relationship table between two or more tables.
On the other hand, it is more effort to delete a multi-column-PK table entry, because you need to give all columns in the multi-column-PK.
Also, check whether your technology stack (programming language) has problems with multi-column-PK.
This is something of a matter of opinion, but I put a synthetic primary key (auto-incremented id) in almost every table I create, including association/junction tables.
Why? Here are some reasons:
If I need to delete or update rows, then the primary key simplifies the process and reduces the change for error.
The primary key captures the insertion order of the rows.
If the row needs to be referred to by another table, then you can refer to it by a primary key.
In some databases, the primary key is used to cluster the data (that is, sort the data on the data pages). An auto-incremented primary key ensures that data goes "at the end". A natural primary key can result in fragmented data.
As an example of the third point, you might have an attendance table that records -- by day -- whether a student attended a class s/he is enrolled in. This could refer to the enrollment table.

Multiple column key or multiple column unique [duplicate]

Here's what's confusing me. I often have composite primary keys in database tables. The bad side of that approach is that I have pretty extra work when I delete or edit entries. However, I feel that this approach is in the spirit of database design.
On the other side, there are friends of mine, who never use composite keys, but rather introduce another 'id' column in a table, and all other keys are just FKs. They have much less work while coding delete and edit procedures. However, I do not know how they preserve uniqueness of data entries.
For example:
Way 1
create table ProxUsingDept (
fkProx int references Prox(ProxID) NOT NULL,
fkDept int references Department(DeptID) NOT NULL,
Value int,
PRIMARY KEY(fkProx,fkDept)
)
Way 2
create table ProxUsingDept (
ID int NOT NULL IDENTITY PRIMARY KEY
fkProx int references Prox(ProxID) NOT NULL,
fkDept int references Department(DeptID) NOT NULL,
Value int
)
Which way is better? What are the bad sides of using the 2nd approach? Any suggestions?
I personally prefer your 2nd approach (and would use it almost 100% of the time) - introduce a surrogate ID field.
Why?
makes life a lot easier for any tables referencing your table - the JOIN conditions are much simpler with just a single ID column (rather than 2, 3, or even more columns that you need to join on, all the time)
makes life a lot easier since any table referencing your table only needs to carry a single ID as foreign key field - not several columns from your compound key
makes life a lot easier since the database can handle the creation of unique ID column (using INT IDENTITY)
However, I do not know how they
preserve uniqueness of data entries.
Very simple: put a UNIQUE INDEX on the compound columns that you would otherwise use as your primary key!
CREATE UNIQUE INDEX UIX_WhateverNameYouWant
ON dbo.ProxUsingDept(fkProx, fkDept)
Now, your table guarantees there will never be a duplicate pair of (fkProx, fkDept) in your table - problem solved!
You ask the following questions:
However, I do not know how they
preserve uniqueness of data entries.
Uniqueness can be preserved by declaring a separate composite UNIQUE index on columns that would otherwise form the natural primary key.
Which way is better?
Different people have different opinions, sometimes strongly held. I think you will find that more people use surrogate integer keys (not that that makes it the "right" solution).
What are the bad sides of using the
2nd approach?
Here are some of the disadvantages to using a surrogate key:
You require an additional index to maintain the unique-ness of the natural primary key.
You sometimes require additional JOINs to when selecting data to get the results you want (this happens when you could satisfy the requirements of the query using only the columns in the composite natural key; in this case you can use the foreign key columns rather than JOINing back to the original table).
There are cases like M:N join tables where composite keys make most sense (and if the nature or the M:N link changes, you'll have to rework this table anyway).
I know it is a very long time since this post was made. But I had to come across a similar situation regarding the composite key so I am posting my thoughts.
Let's say we have two tables T1 and T2.
T1 has the columns C1 and C2.
T2 has the columns C1, C2 and C3
C1 and C2 are the composite primary keys for the table T1 and foreign keys for the table T2.
Let's assume we used a surrogate key for the Table T1 (T1_ID) and used that as a Foreign Key in table T2, if the values of C1 and C2 of the Table T1 changes, it is additional work to enforce the referential ingegrity constraint on the table T2 as we are looking only at the surrogate key from Table T1 whose value didn't change in Table T1. This could be one issue with second approach.

Two Primary Keys

here is the pictorial representation of my partial database. BrandNo is a primary key in Suppliar Table, that is being used as Foreign Key in others.
In LotDetails Table I need BrandName as Foreign Key. This sounds absurd as i can make either
a Single Primary Key OR
a Composite Key
that will be used as Foreign Key.
I know that I can use BrandNo as Foreign Key and Display BrandName, but for the sake of KNOWLEDGE (and yes EASE ofcourse) i want to know that
Is it possible to use two attributes of a table as Foreign Keys separately in different Tables?
EDITTED
BrandNo is just a Serial Number and Brand Name can be the Name of any Brand.
BrandNo is needed in 4 Tables as shown, whereas BrandName is needed in only one table.
Thanks!
Yes! A FK don't need to reference a PK, you even don't need to reference a indexed column but for the sake of relational integrity (and sanity) you must reference a unique valued column (thus is why we "like" to reference a PK or at least a unique non clustered indexed column).
It's sound a bit weird but you can build a relational tableAB holding IdA, IdB and tableA and tableB referencing tableAB respective columns.
btw: a table don't need to own a PK but cannot exist two PK. In general the table is physical ordered by the PK.
Yes that's quite possible. Assuming BrandName is a candidate key on its own then in principle you can reference it in just the same way as BrandNo. In that case BrandName and BrandNo would not be a composite key, they would both be separate candidate keys.
By convention and for simplicity and ease of use it is usual to choose just one key per table to be used for foreign key references. Usually (not always) that is the one designated as "primary" key but it doesn't have to be so if you find a good reason to do otherwise.
When you create foreign key references, the key in the referenced table should be a primary key. It doesn't make sense to have a "partial" reference.
Instead, you should have a Brands table that has a primary key (perhaps BrandId, perhaps BrandName -- I prefer the former). Then tables that need information about a brand can directly reference this table.

What is the difference between an Index and a Foreign Key?

I want to create a database with 3 tables. One for posts and one for tags and one that links posts to tags with the post_id and tag_id functioning as foreign key references.
Can you explain what an Index would be in this scenario and how it differs from a Foreign Key and how that impacts my database design?
an index on a table is a data structure that makes random access to the rows fast and efficient. It helps to optimize the internal organization of a table as well.
A foreign key is simply a pointer to a corresponding column in another table that forms a referential constraint between the two tables.
An index is added as a fast look up for data in the table.
An index can have constraints, in that the column or columns that are used to make the index might have to be unique (unique: only one row in the database is returned for that index, or non-unique: multiple rows can be returned). The primary key for the table is a unique index, and usually only has one column.
A foreign key is a value in a table that references a unique index in another table. It is used as a way to relate to tables together. For example, a child table can look up the one parent row via its column that is a unique index in the parent table.
You'll have foreign keys in the third table. Indexes are not necessary, you need them if you have lots of data where you want to find something by Id quickly. Maybe you'll want an index on posts primary key, but DBMS will probably create it automatically.
Index is a redundant data structure which speeds up some queries.
Foreign key, for practical matters, is a way to make sure that you have no invalid pointers between the rows in your tables (in your case, from the relationship table to posts and tags)
Question: Can you explain what an Index would be in this scenario and how it differs from a Foreign Key and how that impacts my database design?
Your foreign keys in this case are the two columns in your Posts_Tags table. With a foreign key, Each foreign key column must contain a value from the main table it is referencing. In this case, the Posts and Tags tables.
Posts_Tags->PostID must be a value contained in Posts->PostID
Posts_Tags->TagID must be a value contained in Tags->TagID
Think of an index as a column that has been given increased speed and efficiency for querying/searching values from it, at the cost of increased size of your database. Generally, primary keys are indexes, and other columns that require querying/searching on your website, in your case, probably the name of a post (Posts->PostName)
In your case, indexes will have little impact on your design (they are nice to have for speed and efficiency), but your foreign keys are very important to avoid data corruption (having values in them that don't match a post and/or tag).
You describe a very common database construct; it's called a "many-to-many relation".
Indexes shouldn't impact this schema at all. In fact, indexes shouldn't impact any schema. Indexes are a trade-off between space and time: indexes specify that you're willing to use extra storage space, in exchange for faster searches through the database.
Wikipedia has an excellent article about what database indexes are: Index (database)
To use foreign keys in mysql, you need to create indexes on both tables. For example, if you want the field a_id on table b to reference the id field on the table a, you have to create indexes on both a.id and b.a_id before you can create the reference.
Update: here you can read more about it: http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html