在另一个表中引用MySQL ENUM

时间:2016-05-03 22:32:01

标签: mysql enums constraints

我有一个表格SkillLevel创建为

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引用SkillLevel.Level:

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作为ENUM来设置外键?这里的最佳做法是什么?

1 个答案:

答案 0 :(得分:2)

简短回答:枚举存储为数字,因此从技术上讲,您可以将tkSkill作为tinyint加入。

要将其用作外键,您确实需要同时使用tkSkilllevel枚举 - 但您需要levelunique要限定为外键的列,所以要向其添加unique(确切地说:对于InnoDB,如果手动创建索引,则可以使用非唯一外键,但非唯一外键通常是馊主意)。但是你应该考虑sklllevel中你的密钥应该是什么,因为现在它看起来好像你想要Name

独立于将其作为键,您应该将tkSkill定义为(相同的)枚举,以确保它们在某一点上想要更改枚举时意味着相同(这是一个坏主意! )和例如增加另一个技能水平;或者,如果您想直接从表testskill中选择而不需要加入sklllevel,则“阅读”(直接理解)该值;如果你想通过使用enum-namoe将值插入tkSkill(例如'Expert'而不是3,但你可以同时使用它们)而不在sklllevel查找它们。

更长的答案:最佳做法是:不要使用枚举。根据“信念”,只有极少数情况下,枚举可能稍微有用,如果有的话。可能是您不希望使用引用表跳过连接以显示integer-id的textvalue / description。在您的设置中,您实际上使用的是参考表,但仍希望使用枚举。

您最接近使用枚举的最佳做法是将tkSkill定义为testskill中的枚举,并且没有sklllevel - 表(参考表)所有。

但是,我再次敦促你不要使用枚举。您可以将表定义为

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

然后将该id用作tkSkill的外键。甚至

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

然后将tkSkill定义为varchar(20)并将其用作外键 - 但它会占用更多空间,但如果这是因为你首先要使用枚举。

您可以在此处找到枚举的一些背景信息:8 Reasons Why MySQL's ENUM Data Type Is Evil