SQL Server中与MySQL枚举数据类型相对应的是什么?

181

SQL Server 2008有没有像MySQL的enum数据类型一样的东西?


在我想要在SQL Server中实现枚举时,发现了这种有趣的方法。下面链接中提到的方法非常引人注目,因为你可以通过2个中央表来满足所有数据库枚举需求。SQL SERVER - 关系数据库中的枚举 - 最佳实践 - user_v
@user_v 这是“一个真实(查找)表”的反模式的变体。正确的方法是为每个枚举类型使用单独的表,并使用外键(如果您需要查找,这可能不适用于“纯”枚举)。 - Branko Dimitrijevic
@user_v 链接页面上的评论为每个“枚举”使用单独的表格提供了很好的支持,而不是这个答案指定的方式。 - nikodaemus
似乎这是一些答案建议的解决方案,可以使用查找表 (Lookup Table)。 - carloswm85
6个回答

210

它没有。但是有一个模糊的等效物:

mycol VARCHAR(10) NOT NULL CHECK (mycol IN('Useful', 'Useless', 'Unknown'))

25
为什么不使用定义有效值的表,然后使用外键约束呢? - Elaskanator
3
@Elaskanator 我认为这最精确地回答了直接的 OP,而最好的解决方案可能是使用 FK+外部表。 - userfuser
1
谢谢@Elaskanator提醒我显而易见的事情...规范化数据,枚举就不存在了。 - Andrew
11
通常情况下,应用程序代码首先定义枚举值(例如C#中的“enum”),如果使用表格外键引用,则这些被认为是静态的枚举条目可以在运行时修改,这将是不可取的(SQL Server不支持不可变表格的概念)。最后,如果有大量只有少数值的枚举,则最终会向数据库中添加许多表格,更不用说由于插入/删除数据时FK约束检查而导致的额外IO读取。而“CHECK CONSTRAINT”要快得多,也不会导致数据库对象广告。 - Dai
2
我同意@dai的观点。我曾经使用过代码表,但现在认为它们有些过度了。我喜欢CHECK功能和varchar。这使得你可以在C#中使用静态枚举而不需要大量的花哨解决方案。就性能而言,SQL Server几乎可以像索引整数或小整数一样索引字符串。与额外的编码复杂性相比,性能提升微不足道。时间就是金钱。 - James O'Brien
显示剩余8条评论

107

我在这方面找到的最佳解决方案是创建一个查找表,以可能的值作为主键,并创建一个指向查找表的外键。


17
从可维护性的角度来看,比上述检查约束更好的解决方案是什么? - HLGEM
23
这是比枚举更好的解决方案 - 在MySQL中也适用。 - ypercubeᵀᴹ
5
为什么这对MySQL也更好? - BenR
6
@BenRecord:MySQL的枚举类型存在几个问题:8 Reasons Why MySQL's ENUM Data Type Is Evil。我不完全同意它是“邪恶”的,但在使用时必须格外小心。 - ypercubeᵀᴹ
2
@BenR 如果我没记错的话,在MySQL的非严格模式下,无效的枚举可以被插入为NULL。无论条件如何,我的一个以前的团队在MySQL枚举值没有在值列表中指定时无法插入并且不会失败遇到了问题。在查找表上设置外键约束将导致失败。我同意对于MySQL来说查找表更好。 - Joseph Yaduvanshi
显示剩余10条评论

8

你不需要使用T4来完成这个... - Mark Schultheiss
1
哈哈,@MarkSchultheiss 你有注意到这是10年前的事情吗? - Jony Adamit
是的,只是为此添加一条评论 - 并不意味着这是一个错误的答案,甚至在某些地方仍然适用。有时技术会发生变化,想象一下! - Mark Schultheiss

5
CREATE FUNCTION ActionState_Preassigned()
RETURNS tinyint
AS
BEGIN
    RETURN 0
END

GO

CREATE FUNCTION ActionState_Unassigned()
RETURNS tinyint
AS
BEGIN
    RETURN 1
END

-- etc...

在性能至关重要的情况下,仍需使用硬值。

1

针对这个问题,可能最好的解决方案是一个简单的查找表(什么是查找表?)。尽管如此,您可以实现类似以下内容:

解决方案

SQL Server Management Studio (SSMS)

sql server enum implementation

User.Role 是外键,而 Role.Type 是它所引用的主键。在那张表中,您将拥有以下值:

values for enum table

  • 其中的类型必须在两个表中匹配。在这种情况下,该类型为: nvarchar(15)
  • 如果您尝试添加与 Role 表中提供的不同的值到 User.Role,则会出现错误。

enter image description here

SQL 代码

CREATE TABLE [dbo].[User](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Username] [nvarchar](50) NOT NULL,
    [Email] [nvarchar](75) NOT NULL,
    [Password] [nvarchar](25) NOT NULL,
    [Role] [nvarchar](15) NOT NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[User]  WITH CHECK ADD  CONSTRAINT [FK_User_Role] FOREIGN KEY([Role])
REFERENCES [dbo].[Role] ([Type])
GO

ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_Role]
GO

CREATE TABLE [dbo].[Role](
    [Type] [nvarchar](15) NOT NULL,
 CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED 
(
    [Type] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

解决方案2

您可以实现一个类似于这样的查找表:在SQL Server中创建枚举


0
你可以尝试类似这样的代码:
ALTER TABLE dbo.yourTable
ADD CONSTRAINT yourColumn CHECK(yourColumn IN('XL','L','M','S','XS'))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接