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
Would be great if someone provides me a hint to achieve this below scenario.
two foreign keys for table3
FK1 referring to table1 column1
FK2 referring to table 2 column1
Now when i insert a row to table 3 i want only FK1 to be active .
In other words right now mysql will not allow me insert a row until all foreign key constraints are satisfied.
For me- my row should get inserted either if FK1 or FK2 is satisfied. Is there a way I can achieve this ?
There is no real simple way to have an either-or reference constraint; but you can make both FK constraints optional by making the referencing fields nullable.
This would not prevent a row from being inserted with both references null though. To prevent that possibility, you could use a BEFORE INSERT trigger to "throw an error" if an attempt to insert such a row was ever made. Then, you might want to consider a BEFORE UPDATE trigger to prevent rows from being changed in a similar manner.
This is an atypical request, and might indicate that your design has a problem. That being said, one idea which might work would be to create a new table containing just a single column. This column is a primary key and will be populated via an after insert trigger on both table1 and table2. The trigger will only insert if the value is not already in the table. Now, in table3 you may put a foreign key constraint referencing this new column. For the constraint to pass, there only need be one of the two tables having this primary key value.
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 a problem in creating a table with a column that has two foreign Key relationships. Let me explain in detail.
I have three tables:
Table A - columns ID (primary key), Name
Table B - columns ID (primary key), Name
Table C - columns ID, Name, Detail
In C.Detail I have to store data from both other tables (A.ID & B.ID). So I tried to add two foreign key into the column C.Detail. During insert operation in Table B the following error occurs, and the same error message occurs while trying to insert data into Table A.
"The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_C_A". The conflict occurred in database "X", table "dbo.A", column
A.ID."
Please, can anyone help us to rectify this problem? We don't want to add two columns in table C for two foreign keys.
Hopefully waiting for the reply.
I will suggest to introduce two new columns in Table C. (i.e AID and BID).
Create Foregin key on this news columns.
I could be wrong, but I think the way to go about doing this is to create a "parent" table for A and B that has A_B_parent.id(primary_key) and then have A and B both have foreign keys on their id to the parent table. Then C can also have a foreign key to the parent table.
This obviously ends up being really complex, so the better solution might just be to programmatically enforce the constraint rather than using foreign keys and then put a comment on the table.
I thought a foreign key meant that a single row must reference a single row, but I'm looking at some tables where this is definitely not the case. Table1 has column1 with a foreign key constraint on column2 in table2, BUT there are many records in table2 with the same value in column2. There's also non-unique index on column2. What does this mean? Does a foreign key constraint simply mean that at least one record must exist with the right values in the right columns? I thought it meant there must be exactly one such record (not sure how nulls fit in to the picture, but I'm less concerned about that at the moment).
update: Apparently, this behavior is specific to MySQL, which is what I was using, but I didn't mention it in my original question.
From MySQL documentation:
InnoDB allows a foreign key constraint to reference a non-unique key. This is an InnoDB extension to standard SQL.
However, there is a pratical reason to avoid foreign keys on non-unique columns of referenced table. That is, what should be the semantic of "ON DELETE CASCADE" in that case?
The documentation further advises:
The handling of foreign key references to nonunique keys or keys that contain NULL values is not well defined (...) You are advised to use foreign keys that reference only UNIQUE (including PRIMARY) and NOT NULL keys.
Your analysis is correct; the keys don't have to be unique, and constraints will act on the set of matching rows. Not usually a useful behavior, but situations can come up where it's what you want.
When this happens, it usually means that two foreign keys are being linked to each other.
Often the table that would contain the key as a primary key isn't even in the schema.
Example: Two tables, COLLEGES and STUDENTS, both contain a column called ZIPCODE.
If we do a quick check on
SELECT * FROM COLLEGES JOIN STUDENTS ON COLLEGES.ZIPCODE = STUDENTS.ZIPCODE
We might discover that the relationship is many to many. If our schema had a table called ZIPCODES, with primary key ZIPCODE, it would be obvious what's really going on.
But our schema has no such table. Just because our schema has no such table doesn't mean that such data doesn't exist, however. somewhere, out in USPO land, there is just such a table. And both COLLEGES.ZIPCODE and STUDENTS.ZIPCODE are references to that table, even if we don't acknowledge it.
This has more to do with the philosophy of data than the practice of building databases, but it neatly illustrates something fundamental: the data has characteristics that we discover, and not only characteristics that we invent. Of course, what we discover could be what somebody else invented. That's certainly the case with ZIPCODE.
Yes, you can create foreign keys to basically any column(s) in any table. Most times you'll create them to the primary key, though.
If you do use foreign keys that don't point to a primary key, you might also want to create a (non-unique) index to the column(s) being referenced for the sake of performance.
Depends on the RDBMS you're using. I think some do this for you implicitly, or use some other tricks. RTM.
PostgreSQL also refuses this (anyway, even if it is possible, it does not mean it is a good idea):
essais=> CREATE TABLE Cities (name TEXT, country TEXT);
CREATE TABLE
essais=> INSERT INTO Cities VALUES ('Syracuse', 'USA');
INSERT 0 1
essais=> INSERT INTO Cities VALUES ('Syracuse', 'Greece');
INSERT 0 1
essais=> INSERT INTO Cities VALUES ('Paris', 'France');
INSERT 0 1
essais=> INSERT INTO Cities VALUES ('Aramits', 'France');
INSERT 0 1
essais=> INSERT INTO Cities VALUES ('Paris', 'USA');
INSERT 0 1
essais=> CREATE TABLE People (name TEXT, city TEXT REFERENCES Cities(name));
ERROR: there is no unique constraint matching given keys for referenced table "cities"
Necromancing.
As others already said, you shouldn't reference a non-unique key as foreign key.
But what you can do instead (without delete cascade danger) is adding a check-constraint (at least in MS-SQL).
That's not exactly the same as a foreign key, but at least it will prevent the insertion of invalid/orphaned/dead data.
See here for reference (you'll have to port the MS-SQL code to MySQL syntax):
Foreign Key to non-primary key
Edit:
Searching for the reasons for the downvote, according to Mysql CHECK Constraint, MySQL doesn't really support CHECK constraints.
You can define them in your DDL query for compatibility reasons, but they are just ignored...
But as mentioned there, you can create a BEFORE INSERT and BEFORE UPDATE trigger, which will throw an error when the requirements of the data are not met, which is basically the same thing, except that it's an even bigger mess.
As to the question:
I thought a foreign key meant that a single row must reference a
single row, but I'm looking at some tables where this is definitely
not the case.
In any sane RDBMS, this is true.
The fact that this is possible in MySQL is just one more reason why
MySQL is an in-sane RDBMS.
It may be fast, but sacrificing referential integrity and data quality on the altar of speed is not my idea of a quality-rdbms.
In fact, if it's not ACID-compliant, it's not really a (correctly functioning) RDBMS at all.
What database are we talking about? In SQL 2005, I cannot create a foreign key constraint that references a column that does not have a unique constraint (primary key or otherwise).
create table t1
(
id int identity,
fk int
);
create table t2
(
id int identity,
);
CREATE NONCLUSTERED INDEX [IX_t2] ON [t2]
(
[id] ASC
);
ALTER TABLE t1 with NOCHECK
ADD CONSTRAINT FK_t2 FOREIGN KEY (fk)
REFERENCES t2 (id) ;
Msg 1776, Level 16, State 0, Line 1
There are no primary or candidate keys in the referenced table 't2'
that match the referencing column list in the foreign key 'FK_t2'.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
If you could actually do this, you would effectively have a many-to-many relationship, which is not possible without an intermediate table. I would be truly interested in hearing more about this ...
See this related question and answers as well.