非常に遅い答えですが、疑問に思っている人やグーゲルをしている人のために。
はい これは可能ですが、できません 良い習慣であり、それは非常に単純ですが、おそらくあなたの顔に爆発する 自分が何をしているのかよくわからない場合。推奨されません。
しかし、私は用途を見ることができます。たとえば、数百万のレコードの大きなテーブルがあり、例外的な場合には、不明なテーブルまたは複数のテーブルにリンクする必要があります(この場合、多くの )。複数のテーブルがある場合、それらすべてに対して外部キーを作成すると、データベースサイズが大幅に増大します。不明なテーブルは、たとえばテクニカルサポートシステムで、問題が発生する可能性のあるテーブルに記録するためにリンクしたい場合に発生する可能性があります。これは、将来のテーブルを含む、データベース内の(ほぼ)すべてのテーブルである可能性があります。
もちろん、2つが必要です リンク先のフィールド:外部キーフィールドとリンク先のテーブルの名前。それらをforeignId
と呼びましょう およびlinkedTable
linkedTable
列挙型または文字列、できれば列挙型(スペースが少ない)にすることができますが、これは、リンクするさまざまなテーブルが固定されている場合にのみ可能です。
非常にばかげた例を挙げましょう。膨大なユーザーテーブルusers
があります そのうちの一部のユーザーは正確に1つを追加できます プロファイルへの個人的なデータセット。これは、趣味、ペット、彼らが練習するスポーツについてである可能性がありますまたは 彼らの職業。現在、この情報は4つのケースすべてで異なります。 (4つの可能なテーブルは実際にはではありません この構造を正当化するのに十分です)
ここで、linkedTable
としましょう。 可能な値がpets
の列挙型です 、hobbies
、sports
およびprofessions
、4つの異なる構造のテーブルの名前です。 id
としましょう 4つすべてのpkeyです。
たとえば、次のように参加します。
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
これは基本的な冗談を言うためだけのものです。リンクが必要になるのはまれなケースであるため、ユーザーをループするとき(参加せずに)、PHPなどのプログラミング言語でルックアップを実行する可能性が高くなります。
試してみませんか?このテストデータベースを構築して、自分で試すことができます(必ずテストデータベースを使用してください):
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');
次に、最初のクエリを実行します。
ディスカッションのための楽しいメモ:あなたはどうしますか これにインデックスを付けますか?