我有一个表格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来设置外键?这里的最佳做法是什么?
答案 0 :(得分:2)
简短回答:枚举存储为数字,因此从技术上讲,您可以将tkSkill
作为tinyint加入。
要将其用作外键,您确实需要同时使用tkSkill
和level
枚举 - 但您需要level
为unique
要限定为外键的列,所以要向其添加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