Ссылка MySQL перечисление в другой таблице

У меня есть уровень мастерства таблицы, созданный как

CREATE TABLE `sklllevel` (
  `Name` varchar(20) NOT NULL,
  `level` enum('No Experience','Beginner','Expert','Advisor') DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

со значениями

INSERT INTO test.sklllevel (name,level) values ('No Experience','No Experience'),('Beginner','Beginner'),('Expert','Expert'),('Advisor','Advisor');

Я хочу сослаться на уровень мастерства.Уровень С testSkill.tkSkillв другой таблице, созданной как:

CREATE TABLE `testskill` (
  `pkid` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  `tkSkill` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`pkid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Должен ли я иметь TKSKILL в качестве перечисления с тем же набором значений, чтобы установить внешний ключ? Какая здесь лучшая практика?

1 ответ

  1. Краткий ответ: перечисления хранятся в виде числа, поэтому технически вы можете присоединиться к ним в tkSkillкачестве tinyint.

    Чтобы использовать его в качестве внешнего ключа, вы действительно должны иметь оба tkSkill и level будет то же перечисление, но вы должны level быть unique колонки, чтобы квалифицировать в качестве внешнего ключа, поэтому добавьте unique к нему (чтобы быть очень точным: для InnoDB, вы можете иметь неуникальные внешние ключи если вручную создать индекс, но не уникальные внешние ключи, как правило, плохая идея). Но вы должны думать о том, каким sklllevelдолжен быть ваш ключ, так как теперь похоже, что вы Nameхотите быть ключом.

    И независимо от наличия его в качестве ключа вы должны определить tkSkillкак (то же самое) перечисление, чтобы убедиться, что они оба означают то же самое, если вы в какой-то момент хотели бы изменить перечисления (что это плохая идея! или если вы хотите «прочитать» (непосредственно понять) значение, когда вы выбираете непосредственно из таблицы testskillбез необходимости присоединенияsklllevel; и если вы хотите вставить значения в tkSkill, используя их перечисление (например, ‘Expert’ вместо 3, но вы можете использовать оба), не глядя на них sklllevel.

    Более длинный ответ: Лучшая практика: не используйте перечисления. В зависимости от» убеждения», нет ничего, чтобы только несколько случаев, когда перечисления могут быть немного полезны, если вообще. Одним из них может быть то, что вы не хотите использовать ссылочную таблицу, чтобы пропустить соединение для отображения textvalue/description of a integer-id. В настройках вы фактически используете справочную таблицу и по-прежнему хотите использовать перечисления.

    Ближе всего к наилучшей практике использования перечислений можно было бы определить tkSkillкак перечисление testskillи вообще не иметьsklllevel-table (справочную таблицу).

    Но опять же, я призываю вас не использовать перечисления. Таблицу можно определить как

    CREATE TABLE `sklllevel` (
      `Id` tinyint(4) primary key,
      `Name` varchar(20) NOT NULL,
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    а затем использовать этот идентификатор в качестве внешнего ключа для tkSkill. Или даже

    CREATE TABLE `sklllevel` (
      `Name` varchar(20) primary key
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    а затем определите tkSkillкак varchar(20)и используйте это как внешний ключ — он будет использовать больше места, хотя, но у вас будут «читаемые» значения в таблице, если это было причиной использования перечислений в первую очередь.

    Здесь вы можете найти некоторые предпосылки к перечислениям: 8 причин, почему тип данных перечисления MySQL является злом