Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MYSQL - Eine Spalte, die auf mehrere Tabellen verweist

Eine sehr späte Antwort, aber für alle, die sich fragen und googeln.

JA dies ist möglich, aber NICHT gute Praxis und obwohl es ziemlich einfach ist, wird es Ihnen wahrscheinlich um die Ohren fliegen wenn Sie nicht sehr bewusst sind, was Sie tun. Nicht empfohlen.

Ich sehe jedoch Verwendungsmöglichkeiten. Beispielsweise haben Sie eine große Tabelle mit Millionen von Datensätzen und möchten in Ausnahmefällen auf unbekannte oder mehrere Tabellen verlinken (in diesem Fall sollten es besser viele sein ). Wenn Sie bei mehreren Tabellen einen Fremdschlüssel für alle erstellen würden, wäre dies eine enorme Aufblähung Ihrer Datenbankgröße. Eine unbekannte Tabelle wäre beispielsweise in einem technischen Supportsystem möglich, wo Sie einen Link zu einem Datensatz in einer Tabelle erstellen möchten, in der möglicherweise ein Problem vorliegt, und dies könnten (fast) alle Tabellen in der Datenbank sein, einschließlich zukünftiger.

Natürlich brauchen Sie zwei zu verknüpfende Felder:ein Fremdschlüsselfeld und der Name der Tabelle, mit der es verknüpft wird. Nennen wir sie foreignId und linkedTable

linkedTable könnte eine Aufzählung oder ein String sein, vorzugsweise Aufzählung (weniger Platz), aber das ist nur möglich, wenn die verschiedenen Tabellen, auf die Sie verlinken möchten, festgelegt sind.

Lassen Sie uns ein extrem dummes Beispiel geben. Sie haben eine riesige Benutzertabelle users von denen einige Benutzer genau eine hinzufügen können persönlichen Datensatz zu ihrem Profil hinzufügen. Dabei kann es sich um ein Hobby, ein Haustier oder einen Sport handeln, den sie ausüben oder ihren Beruf. Nun ist diese Info in allen vier Fällen unterschiedlich. (4 mögliche Tabellen sind in Wirklichkeit nicht genug, um diese Struktur zu rechtfertigen)

Sagen wir jetzt linkedTable ist eine Aufzählung mit möglichen Werten pets , hobbies , sports und professions , das sind die Namen von vier unterschiedlich strukturierten Tabellen. Sagen wir id ist der pkey in allen vieren.

Sie treten beispielsweise wie folgt bei:

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

Dies ist nur ein einfacher Scherz. Da Sie den Link wahrscheinlich nur in seltenen Fällen benötigen, werden Sie die Suche eher in Ihrer Programmiersprache wie PHP durchführen, wenn Sie die Benutzer durchlaufen (ohne Join).

Ausprobieren? Sie können es selbst versuchen, indem Sie diese Testdatenbank erstellen (stellen Sie sicher, dass Sie eine Testdatenbank verwenden):

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');

Führen Sie dann die erste Abfrage aus.

Lustige Notiz zur Diskussion:Wie würden Sie indexieren?