sql >> Databasteknik >  >> RDS >> Mysql

MySQL:Två n:1-relationer, men inte båda samtidigt

Din nuvarande design kallas exklusiva bågar där sets tabellen har två främmande nycklar och behöver exakt en av dem vara icke-null. Detta är ett sätt att implementera polymorfa associationer, eftersom en given främmande nyckel endast kan referera till en måltabell.

En annan lösning är att göra en gemensam "supertable" som båda users och schools referenser och använd sedan det som förälder till 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

Du kan tänka på detta som analogt med ett gränssnitt i OO-modellering:

interface SetOwner { ... }

class User implements SetOwner { ... }

class School implements SetOwner { ... }

class Set {
  SetOwner owner;
}

Angående dina kommentarer:

Låt SetOwners-tabellen generera id-värden. Du måste infoga i SetOwners innan du kan infoga i antingen Users eller Schools. Så gör ID:n i Users and Schools inte automatisk ökning; använd bara värdet som genererades av SetOwners:

INSERT INTO SetOwners DEFAULT VALUES; -- generates an id
INSERT INTO Schools (id, name, location) VALUES (LAST_INSERT_ID(), 'name', 'location');

På så sätt kommer inget givet id-värde att användas för både en skola och en användare.

Du kan säkert göra detta. Faktum är att det kan finnas andra kolumner som är gemensamma för både användare och skolor, och du kan lägga dessa kolumner i supertabellen SetOwners. Detta kommer in på Martin Fowlers Klassbordsarv mönster.

Du måste göra en join. Om du frågar från en given uppsättning och du vet att den tillhör en användare (inte en skola) kan du hoppa över att gå med i SetOwners och gå direkt med användare. Joins behöver inte nödvändigtvis ske med främmande nycklar.

SELECT u.name FROM Sets s JOIN Users u ON s.SetOwner_id = u.id WHERE ...

Om du inte vet om en given uppsättning tillhör en användare eller en skola, måste du göra en yttre koppling till båda:

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 ...

Du vet att SetOwner_id måste matcha den ena eller den andra tabellen, användare eller skolor, men inte båda.



  1. SQL IN vs SQL FINNS

  2. Hur man läser versionsnummer från en databasfil i Android som placeras i tillgångsmappen

  3. Hur kan man få unika värden från datatabellen med hjälp av dql?

  4. Django distinkt grupp efter fråga på två fält