sql >> Database >  >> RDS >> Mysql

MYSQL - Eén kolom waarnaar wordt verwezen naar meerdere tabellen

Een erg laat antwoord, maar voor wie het zich afvraagt ​​&googelt.

JA dit kan, maar het is NIET goede gewoonte en hoewel het vrij eenvoudig is, zal het waarschijnlijk in je gezicht ontploffen als je niet erg bewust bent van wat je doet. Niet aanbevolen.

Ik zie echter toepassingen. U heeft bijvoorbeeld een grote tabel met miljoenen records en u wilt in uitzonderlijke gevallen linken naar onbekende of meerdere tabellen (in dat geval kunt u beter veel ). Als u met meerdere tabellen een externe sleutel voor alle tabellen zou maken, zou dat een enorme ophoping van uw database-omvang zijn. Een onbekende tabel zou bijvoorbeeld mogelijk zijn in een technisch ondersteuningssysteem, waar u een koppeling wilt maken naar een tabel waar er een probleem zou kunnen zijn, en dit kunnen (bijna) alle tabellen in de database zijn, inclusief toekomstige.

Natuurlijk heb je twee nodig velden om mee te linken:een veld met een refererende sleutel en de naam van de tabel waarnaar wordt gelinkt. Laten we ze foreignId noemen en linkedTable

linkedTable kan een enum of een string zijn, bij voorkeur enum (minder spatie), maar dat kan alleen als de verschillende tabellen waarnaar je wilt linken vast zijn.

Laten we een extreem dom voorbeeld geven. Je hebt een enorme gebruikerstabel users waarvan sommige gebruikers precies één . kunnen toevoegen persoonlijke set gegevens naar hun profiel. Dit kan gaan over een hobby, een huisdier, een sport die ze beoefenen of hun beroep. Nu is deze informatie in alle vier de gevallen anders. (4 mogelijke tabellen is in werkelijkheid niet genoeg om deze structuur te rechtvaardigen)

Laten we nu zeggen linkedTable is een opsomming met mogelijke waarden pets , hobbies , sports en professions , wat de namen zijn van vier verschillend gestructureerde tabellen. Laten we zeggen id is de pkey in alle vier.

Je sluit je bijvoorbeeld als volgt aan:

SELECT * FROM users 
    LEFT JOIN  pets        ON linkedTable = 'pets'        AND foreignId = pets.id
    LEFT JOIN  hobbies     ON linkedTable = 'hobbies'     AND foreignId = hobbies.id
    LEFT JOIN  sports      ON linkedTable = 'sports'      AND foreignId = sports.id
    LEFT JOIN  professions ON linkedTable = 'professions' AND foreignId = professions.id

Dit is gewoon om een ​​simpele grap te maken. Aangezien je de link waarschijnlijk alleen in zeldzame gevallen nodig hebt, zul je waarschijnlijk de zoekopdracht in je programmeertaal, zoals PHP, doen als je door de gebruikers loopt (zonder join).

Wil je uitproberen? Je kunt het zelf proberen met het bouwen van deze testdatabase (zorg ervoor dat je een testdatabase gebruikt):

CREATE TABLE IF NOT EXISTS `users` (
    `id` INT NOT NULL AUTO_INCREMENT , 
    `name` VARCHAR(100) NOT NULL , 
    `linkedTable` ENUM('pets','hobbies','sports','professions') NULL DEFAULT NULL , 
    `foreignId` INT NULL DEFAULT NULL , 
  PRIMARY KEY (`id`), INDEX (`linkedTable`)
) ;

CREATE TABLE  IF NOT EXISTS `pets` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `animalTypeId` INT NOT NULL , 
    `name` VARCHAR(100) NOT NULL , 
    `colorId` INT NOT NULL , 
  PRIMARY KEY (`id`), INDEX (`animalTypeId`), INDEX (`colorId`)
) ;

CREATE TABLE  IF NOT EXISTS `hobbies` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `hobbyTypeId` INT NOT NULL , 
    `hoursPerWeekSpend` INT NOT NULL , 
    `websiteUrl` VARCHAR(300) NULL , 
  PRIMARY KEY (`id`), INDEX (`hobbyTypeId`)
) ;

CREATE TABLE  IF NOT EXISTS `sports` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `sportTypeId` INT NOT NULL , 
    `hoursPerWeekSpend` INT NOT NULL , 
    `nameClub` VARCHAR(100) NULL , 
    `professional` TINYINT NOT NULL DEFAULT 0, 
  PRIMARY KEY (`id`), INDEX (`sportTypeId`)
) ;

CREATE TABLE  IF NOT EXISTS `professions` ( 
    `id` INT NOT NULL AUTO_INCREMENT , 
    `professionId` INT NOT NULL , 
    `hoursPerWeek` INT NOT NULL , 
    `nameCompany` VARCHAR(100) NULL , 
    `jobDescription` VARCHAR(400) NULL, 
  PRIMARY KEY (`id`), INDEX (`professionId`)
) ;


INSERT INTO `users` (`id`, `name`, `linkedTable`, `foreignId`) 
   VALUES 
   (NULL, 'Hank', 'pets', '1'), 
   (NULL, 'Peter', 'hobbies', '2'), 
   (NULL, 'Muhammed', 'professions', '1'), 
   (NULL, 'Clarice', NULL, NULL), 
   (NULL, 'Miryam', 'professions', '2'), 
   (NULL, 'Ming-Lee', 'hobbies', '1'), 
   (NULL, 'Drakan', NULL, NULL), 
   (NULL, 'Gertrude', 'sports', '2'), 
   (NULL, 'Mbase', NULL, NULL);


INSERT INTO `pets` (`id`, `animalTypeId`, `name`, `colorId`) 
VALUES (NULL, '1', 'Mimi', '3'), (NULL, '2', 'Tiger', '8');

INSERT INTO `hobbies` (`id`, `hobbyTypeId`, `hoursPerWeekSpend`, `websiteUrl`) 
VALUES (NULL, '123', '21', NULL), (NULL, '2', '1', 'http://www.freesoup.org');

INSERT INTO `sports` (`id`, `sportTypeId`, `hoursPerWeekSpend`, `nameClub`, `professional`) 
VALUES (NULL, '2', '3', 'Racket to Racket', '0'), (NULL, '12', '34', NULL, '1');

INSERT INTO `professions` (`id`, `professionId`, `hoursPerWeek`, `nameCompany`, `jobDescription`) 
VALUES (NULL, '275', '40', 'Ben & Jerry\'s', 'Ice cream designer'), (NULL, '21', '24', 'City of Dublin', 'Garbage collector');

Voer vervolgens de eerste query uit.

Leuke opmerking voor discussie:Hoe zou je dit indexeren?



  1. Hoe SQLite Sum() werkt

  2. twee SELECT-query's samenvoegen

  3. Verbindingspooling met Pgbouncer op PostgreSQL 9.0

  4. Hoe Postgres bytea-kolom als bestand te downloaden