I have seen similar posts and have not found a definitive answer.
I have a series of tables that store data about certain events. Each of these tables have the same structure. Each of these tables has a foreign key constraint for an id showing what item the data is related to.
Each of these tables id structure is also the same CHAR(24). The tables these ids come from must remain separate because they are all completely different.
I am interested in combining all of my data tables into one with a foreign key being constrained to one of 3 tables. So, a row in my data table will have to have an id that is present in one of the three tables. Additionally this foreign key will need the possibility of ON DELETE settings. Is this possible? And to that, is this poor design?
Items A
- id
- ...
Items B
- id
- ...
Items C
- id
- ...
Data
- id FK
No. What you're describing is sometimes called polymorphic-associations but it should be a clue that it's not good design because you can't make a foreign key constraint for it. That is, the FOREIGN KEY syntax only allows you to reference one table, not three.
The only way you could make a real foreign key constraint that performs ON DELETE actions is to make three separate foreign keys:
Data
- idA FK
- idB FK
- idC FK
For a given row in Data, presumably only one of these three foreign keys would be non-NULL. The other two would be NULL. Ensuring this could be done in a trigger or CHECK constraint, or else you would just have to implement it in application logic (i.e. don't insert a row with more than one of these columns non-NULL).
Polymorphic associations, that is storing a single column that may reference one of three different tables, is not a valid relational design.
You can see past answers I've written about polymorphic associations: https://stackoverflow.com/search?q=%5Bpolymorphic-associations%5D+user%3A20860
Related
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.
So I have 3 tables:
Table: Albums
Columns: Id, Name, Description, Author, Folderpath, Thumbnail, Upvotes, Downvotes
Table: AlbumsConnection
Columns: Id, AlbumId, AlbumImagesId
Table: AlbumImages
Columns: Id, InAlbum, Imagepath
So far I've been using these tables without actually using foreign keys. Am I supposed to use foreign keys here? I understand that I'd have to add 2 foreign keys to AlbumsConnection, 1 for each table and each foreign key will reference to the primary keys ( which are the ids ) of the other 2 tables. Is that correct?
Foreign keys help ensure relational integrity of the database. There is no requirement for declaring them explicitly, but it is a good idea, particularly if you are learning to use databases.
The foreign key let's the database know that a column in one table is related to a column in another table. I don't think MySQL's optimizer uses this information explicitly, although it does create an index on the foreign key column (unlike most other databases).
In addition, a declared foreign key relationship can help you deal with changes to the database. It will prevent invalid albums from being inserted into the junction table. If you delete an album, it gives you control over how the deletion and updating is handled (via cascading constraints).
I have referenced a foreign key to a primary key. Whenever I click on create new project, I am storing the project Id in the reference key but I want to store multiple projects.
Can anyone please help?
Even your query is not much clear that what issue you are getting but you can understand foreign key concept as per below-
If you create a foreign key in any child table and referenced it with master table means you are saying that child table can contain a value only its reference exists in parent table.
Normally in mostly cases we want to use normalization and basic concept is that we keep unique value in master table (mostly primary key) and its child rows (multiple) in its child table.
Suppose we have two tables customer and order then customer table contains unique customer but as same customer can order multiple times, so order tables may contains multiple customers.
In your case whenever you will create a new project then a new project_id will insert in master i.e. project table and its multiple sub-attributes in its child tables. Now whats the issue you are facing. Please explain.
I am stuck in a problem where i have to find cardinality of a relationship between tables using mysql. Following this post MySQL: How to determine foreign key relationships programmatically?
I have found all tables related to my table and the columns which are foreign key. Now i also want to find the cardinality of relationship i.e. one-to-one, one-to-many or many-to-many. Any ideas or snippets would be highly appreciated
Let us assume that table A has a foreign key f which refers to the primary key k of table B. Then you can learn the following from the schema:
If there is a UNIQUE constraint on A.f, then there can be at most one row in A for every row in B. Note that in the case of multi-column indices, all columns of the unique constraint must be part of the foreign key. You can use SHOW INDEX FROM tablename WHERE Non_unique = 0 to obtain information on the uniqueness constraints of a table.
If A.f is declared NOT NULL, then there will always be at least one row in B for every row in A. You can use SHOW COLUMNS FROM tablename to list the columns and see which of them allow NULL values.
If you interpret “one” as “zero or one”, then you get a one-to-one relation using a unique constraint, and a many-to-one relation (i.e. many rows in A referring to one row in B) without such a unique constraint.
A many-to-many relation would be modeled using a separate table, where each row represents one element of the relation, with many-to-one relations for both foreign keys it contains.
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.