sql >> Database teknologi >  >> RDS >> Mysql

MYSQL - Én kolonne refereret til flere tabeller

Et meget sent svar, men for den, der undrer sig og googler.

JA dette kan gøres, men det er IKKE god praksis, og selvom det er ret simpelt, vil det sandsynligvis blæse op i dit ansigt hvis du ikke er meget opmærksom på, hvad du laver. Anbefales ikke.

Jeg kan dog se anvendelser. For eksempel har du en stor tabel med millioner af poster, og du vil i undtagelsestilfælde linke til ukendte eller flere tabeller (i så fald er det bedre at være mange ). Med flere tabeller, hvis du ville lave en fremmednøgle til dem alle, ville det være et stort opsving i din databasestørrelse. En ukendt tabel ville være mulig for eksempel i et teknisk supportsystem, hvor man ønsker at linke til record i en tabel, hvor der kan være et problem, og det kan være (næsten) alle tabeller i databasen, inklusive fremtidige.

Selvfølgelig skal du bruge to felter at linke til:et fremmednøglefelt og navnet på den tabel, den linker til. Lad os kalde dem foreignId og linkedTable

linkedTable kunne være en enum eller en streng, helst enum (mindre plads), men det er kun muligt, hvis de forskellige tabeller, du vil linke til, er faste.

Lad os give et ekstremt dumt eksempel. Du har en enorm brugertabel users hvoraf nogle brugere kan tilføje præcis én personlige datasæt til deres profil. Dette kan handle om en hobby, et kæledyr, en sport, de dyrker eller deres erhverv. Nu er denne information anderledes i alle fire tilfælde. (4 mulige tabeller er i virkeligheden ikke). nok til at retfærdiggøre denne struktur)

Lad os nu sige linkedTable er en enum med mulige værdier pets , hobbies , sports og professions , som er navnene på fire forskelligt strukturerede tabeller. Lad os sige id er pkey i dem alle fire.

Du tilmelder dig f.eks. på følgende måde:

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

Dette er bare for at give en grundlæggende spøg. Da du sandsynligvis kun har brug for linket i sjældne tilfælde, vil du mere sandsynligt foretage opslag i dit programmeringssprog, som PHP, når du går gennem brugerne (uden joinforbindelse).

Vil du prøve? Du kan prøve det selv med at bygge denne testdatabase (sørg for at bruge en testdatabase):

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 derefter den første forespørgsel.

Sjov bemærkning til diskussion:Hvordan ville du indeksere dette?



  1. Hvordan gemmer man europæisk valuta i MySQL?

  2. Sådan fjerner du førende og efterfølgende hvidt mellemrum i SQL Server - TRIM()

  3. DB-migrering med NextForm Multi-Table Wizard

  4. Opret forbindelse til MSSQL-databasen ved hjælp af Flask-SQLAlchemy