views:

2750

answers:

6

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.

+4  A: 

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.

chaos
Thanks for the help, Chaos. This really messes up my understanding of foreign keys though...
allyourcode
At first, I was a little confused about what "your analysis" was supposed to refer to. For other readers, I think you meant it's possible for a foreign key to refer to more than one row, as long as there's _at least_ one row.
allyourcode
Your understanding of foreign keys is rightfully messed up, because this is a bogus answer. Even if you find a database where you can do this (I did not test MySQL), it would very, _very_ bad database design to implement such a foreign key relationship.
cdonner
@cdonner: Well, I would've thought that being *correct* would've been some defense against my answer being 'bogus'. What am I supposed to do, lie tell the guy you can't do it since I consider it a generally bad idea (which I do)? And yes, you can do it in mysql.
chaos
@allyourcode: Really, you shouldn't throw out your former understanding of foreign keys. It's correct for 99% of non-pathological cases.
chaos
@chaos: I stand corrected - at least somewhat. I know little about MySQL. Can you give one example where that would be a useful practice?
cdonner
+3  A: 

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.

Evan
MySQL (InnoDB) requires a (left-hand) index on the referencing and referenced columns. JADP.
chaos
A: 

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.

cdonner
I'm using MySQL.
allyourcode
@allyourcode: do you mind sharing what these 2 tables do in your database that have this m:n foreign key relationship?
cdonner
A: 

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.

Walter Mitty
You lost me at "two foreign keys are being linked to each other". I really don't know what that could mean.
allyourcode
+1  A: 

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"
bortzmeyer
This was not mentioned. And, since MySQL is especially sloppy in checks, constraints and controls, it would not surprise me that integrity references to non-unique keys are possible with MySQL.
bortzmeyer
I don't think it has to do with being sloppy. Postgresql reserves this functionality in the keyword `MATCH PARTIAL` it just isn't implemented afaik.
Evan Carroll
+2  A: 

From MySQL documentation:

Deviation from SQL standards: A FOREIGN KEY constraint that references a non-UNIQUE key is not standard SQL. It 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?

Hobbes
Thanks for citing MySQL's documentation. I didn't specifically mention MySQL in my question, but that is what I was using. I will update my question to reflect this.
allyourcode