我有一个创建为的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并使用相同的值集来设置外键?这里最好的做法是什么?
简单回答:枚举存储为一个数字,因此从技术上讲,您可以将它们与tkSkill
连接为一个tinyint。
要将其用作外键,确实需要tkSkill
和level
都是同一个枚举,但需要level
是unique
列才能作为外键,所以请将unique
添加到其中(确切地说:对于InnoDB,如果手动创建索引,则可以使用非唯一外键,但非唯一外键通常是个坏主意)。但您应该考虑sklllevel
中的密钥应该是什么,因为现在看起来您似乎希望Name
成为密钥。
独立于将其作为关键字,您应该将tkSkill
定义为(相同的)枚举,以确保它们的含义相同,如果您曾想更改枚举(这是个坏主意!),例如添加另一个技能级别;或者如果您想在不需要加入sklllevel
的情况下直接从表testskill
中选择时"读取"(直接理解)该值;如果你想通过使用它们的枚举namoe(例如"Expert"而不是3,但你可以同时使用这两个)将值插入tkSkill,而无需在sklllevel
中查找它们。
答案更长:最佳做法是:不要使用枚举。根据"信念"的不同,在少数情况下,如果有的话,枚举可能会稍微有用。一种可能是,您不想使用引用表跳过连接来显示整数id的文本值/描述。在您的设置中,您实际上使用的是一个引用表,并且仍然希望使用枚举。
使用枚举最接近最佳实践的方法是将tkSkill
定义为testskill
中的枚举,并且根本没有sklllevel
表(引用表)。
但是,我再次敦促您不要使用枚举。您可以将表格定义为
CREATE TABLE `sklllevel` (
`Id` tinyint(4) primary key,
`Name` varchar(20) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
然后使用该id作为CCD_ 17的外键。甚至
CREATE TABLE `sklllevel` (
`Name` varchar(20) primary key
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
然后将tkSkill
定义为varchar(20)
,并将其用作外键-这将使用更多的空间,但如果这是您首先使用枚举的原因,则表中会有"可读"值。
在这里你可以找到一些枚举的背景:MySQL的ENUM数据类型是邪恶的的8个原因