Váš aktuální návrh se nazývá exkluzivní oblouky kde sets
tabulka má dva cizí klíče a potřebuje, aby právě jeden z nich nebyl nulový. Toto je jeden způsob, jak implementovat polymorfní asociace, protože daný cizí klíč může odkazovat pouze na jednu cílovou tabulku.
Dalším řešením je vytvořit společnou "supertable", kterou oba users
a schools
odkazy a poté je použijte jako rodiče sets
.
create table set_owner
create table users
PK is also FK --> set_owner
create table schools
PK is also FK --> set_owner
create table sets
FK --> set_owner
Můžete si to představit jako analogii k rozhraní v modelování OO:
interface SetOwner { ... }
class User implements SetOwner { ... }
class School implements SetOwner { ... }
class Set {
SetOwner owner;
}
K vašim komentářům:
Nechte tabulku SetOwners vygenerovat hodnoty id. Musíte vložit do SetOwners, než budete moci vložit buď do Users nebo Schools. Takže nastavte ID v Users and Schools ne automatické zvyšování; stačí použít hodnotu, která byla vygenerována SetOwners:
INSERT INTO SetOwners DEFAULT VALUES; -- generates an id
INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location');
Tímto způsobem nebude použita žádná daná hodnota id jak pro školu, tak pro uživatele.
Určitě to dokážeš. Ve skutečnosti mohou existovat další sloupce, které jsou společné pro uživatele i školy, a tyto sloupce byste mohli umístit do supertabulky SetOwners. To se dostane do dědičnosti tabulky tříd Martina Fowlera vzor.
Musíte se připojit. Pokud se dotazujete z dané sady a víte, že patří uživateli (ne škole), můžete přeskočit připojení k SetOwners a připojit se přímo k uživatelům. Spojení nemusí nutně probíhat pomocí cizích klíčů.
SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ...
Pokud nevíte, zda daná sada patří uživateli nebo škole, budete muset provést vnější spojení k oběma:
SELECT COALESCE(u.name, sc.name) AS name
FROM Sets s
LEFT OUTER JOIN Users u ON s.SetOwner_id = u.id
LEFT OUTER JOIN Schools sc ON s.SetOwner_id = sc.id
WHERE ...
Víte, že SetOwner_id musí odpovídat jedné nebo druhé tabulce, Users nebo Schools, ale ne oběma.