Ett väldigt sent svar, men för den som undrar &googlar.
JA detta kan göras, men det är INTE bra praxis och även om det är ganska enkelt, kommer det förmodligen att sprängas i ansiktet om du inte är så medveten om vad du gör. Rekommenderas inte.
Däremot kan jag se användningsområden. Till exempel har du en stor tabell med miljontals poster, och du vill i undantagsfall länka till okända eller flera tabeller (i så fall är det bättre att vara många ). Med flera tabeller, om du skulle skapa en främmande nyckel för dem alla, skulle det vara en enorm ökning av din databasstorlek. En okänd tabell skulle vara möjlig till exempel i ett tekniskt supportsystem, där du vill länka till post i en tabell där det kan finnas ett problem, och det kan vara (nästan) alla tabeller i databasen, inklusive framtida.
Naturligtvis behöver du två fält att länka till:ett främmande nyckelfält och namnet på tabellen den länkar till. Låt oss kalla dem foreignId
och linkedTable
linkedTable
kan vara en enum eller en sträng, helst enum (mindre utrymme), men det är bara möjligt om de olika tabellerna du vill länka till är fixade.
Låt oss ge ett extremt fånigt exempel. Du har en enorm användartabell users
varav vissa användare kan lägga till exakt en personlig uppsättning data till sin profil. Det här kan handla om en hobby, ett husdjur, en sport de utövar eller deras yrke. Nu är denna information annorlunda i alla fyra fallen. (4 möjliga tabeller är i verkligheten inte tillräckligt för att motivera denna struktur)
Låt oss nu säga linkedTable
är en uppräkning med möjliga värden pets
, hobbies
, sports
och professions
, som är namnen på fyra olika strukturerade tabeller. Låt oss säga id
är nyckeln i alla fyra.
Du går med till exempel på följande sätt:
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
Detta är bara för att ge ett grundläggande skämt. Eftersom du förmodligen bara behöver länken i sällsynta fall, kommer du mer sannolikt att göra uppslagningen i ditt programmeringsspråk, som PHP, när du går igenom användarna (utan att gå med).
Vill du prova? Du kan prova det själv med att bygga denna testdatabas (se till att du använder en testdatabas):
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');
Kör sedan den första frågan.
Kul kommentar för diskussion:Hur skulle du indexera detta?