sql >> Database >  >> RDS >> Mysql

MySQL:Twee n:1 relaties, maar niet beide tegelijk

Uw huidige ontwerp heet exclusieve bogen waar de sets tabel heeft twee externe sleutels en er moet er precies één niet-null zijn. Dit is een manier om polymorfe associaties te implementeren, aangezien een gegeven externe sleutel slechts naar één doeltabel kan verwijzen.

Een andere oplossing is om een ​​gemeenschappelijke "supertable" te maken die zowel users en schools referenties, en gebruik dat dan als de ouder van 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

Je kunt dit zien als analoog aan een interface in OO-modellering:

interface SetOwner { ... }

class User implements SetOwner { ... }

class School implements SetOwner { ... }

class Set {
  SetOwner owner;
}

Over uw opmerkingen:

Laat de SetOwners-tabel id-waarden genereren. U moet in SetOwners invoegen voordat u kunt invoegen in Gebruikers of Scholen. Dus maak de id's in Gebruikers en Scholen niet automatisch ophogen; gebruik gewoon de waarde die is gegenereerd door SetOwners:

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

Op deze manier wordt er geen bepaalde ID-waarde gebruikt voor zowel een school als een gebruiker.

Dit kun je zeker doen. Er kunnen zelfs andere kolommen zijn die zowel voor gebruikers als voor scholen gelden, en u kunt deze kolommen in de supertabel SetOwners plaatsen. Dit komt in Martin Fowler's Class Table Inheritance patroon.

Je moet een join doen. Als u een vraag stelt vanuit een bepaalde Set en u weet dat deze van een gebruiker is (niet van een school), kunt u de deelname aan SetOwners overslaan en rechtstreeks deelnemen aan Gebruikers. Joins hoeven niet per se met externe sleutels te gaan.

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

Als je niet weet of een bepaalde set toebehoort aan een gebruiker of een school, moet je een outer join doen voor beide:

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

U weet dat de SetOwner_id moet overeenkomen met de ene of de andere tabel, Gebruikers of Scholen, maar niet beide.



  1. MySQL regex-query niet hoofdlettergevoelig

  2. MYSQL - Gegevens selecteren uit de tweede rij in een grote tabel

  3. Mac OS X + Python + Django + MySQL

  4. Ondersteunt PostgreSQL het transparant comprimeren van tabellen (fragmenten)?