在MySQL数据库中存储枚举类型

9
我需要为我的情况找到最干净和高效的解决方案。我试图将学生的成绩存储在MySQL数据库中。学生可能是“缺席”或“抄袭案例”,我也想在数据库中存储这样的信息。
我考虑为上述情况分配代码,如-1表示“缺席”,-2表示“抄袭案例”等。这些代码将仅存储在Marks列中。
此外,在使用select查询读取它们时,我应该只得到它们的显示值,即“ABSENT”,“COPY CASE”等。
所有这些是否只能在DB端实现?
还是我只需要在应用程序级别上实现这些东西?
Java是否有可用于此类功能的API?
5个回答

8

MySQL支持枚举类型:

CREATE TABLE students (name varchar(64), mark ENUM('ABSENT','COPY CASE' ));
INSERT INTO students VALUES ('john', 'COPY CASE');

在Java中,您可以将此列视为字符串类型列,但是在数据库中,值存储得很有效,并且尝试存储不包含在枚举中的值将导致错误。


1
第二个要求可以通过引用完整性来满足。 - Sanjay T. Sharma

4

将其name()(字符串版本)存储到数据库中,在从数据库中读取时使用valueOf()创建它


1
我考虑将上述情况的代码存储为-1表示“缺席”,-2表示“复制案例”等。这些代码将仅存储在Marks列中。
我更喜欢有一个单独的列,比如`状态(status)`,其中包含像`缺席(ABSENT)`、`复制案例(COPY CASE)`这样的值,并具有默认值`出现(APPEARED)`。
Marks列将保持分开。
在视图层,你可以做类似这样的事情:
如果状态为`出现(APPEARED)`,则显示Marks字段,否则显示状态字段。

1
这绝对比将分数和考试状态存储在同一列中要好。并且您不会在查找例如AVG(mark)的查询中意外地得到错误的结果。 - ypercubeᵀᴹ

1
如果枚举字符串表示形式比较繁琐,并且数据库很大(经常根据这些枚举进行检查),我可能会将每个枚举映射到一个整数常量(不是ordinal(),而是您自己的自定义整数值),并在枚举上编写方法以获取和创建这些值的枚举。这样,您将能够相当有效地存储枚举。
public enum Status {

  ABSENT(1), COPY_PASTE(2);

  int value;

  private Status(int value) {
      this.value = value;
  }

  public int getValue() {
      return this.value;
  }

  public static Status ofStatusCode(int value) {
      // retrieve status from status code
  }

}

只是想提醒一下,虽然我同意Sanjay的观点,即使用数字类型表示枚举通常比使用字符串类型更有效(在性能和空间方面),但Enum类型是一个例外,它将在内部使用16位无符号(short)以有效地存储值,并且我从未遇到过性能问题。 - Anthony Accioly

0

MySQL 有自己的 ENUM 类型。正如 @Jigar 指出的那样,你可以使用 Enum.getName 来获取 Java 中表示枚举的字符串以进行持久化,将字段从数据库中检索为字符串并使用 Enum.valueOf 加载枚举常量。

你还可以使用 Enum.ordinal() + 1 来获取整数进行持久化(MySQL 还支持直接使用整数索引与 ENUM 类型)并发出类似以下的查询:

SELECT enum_col-1 FROM tbl_name;

为了检索序数(对于具有无效枚举值的行,它将检索-1)。

此外,MyEnumType value = MyEnumType.values()[ordinal] 可以将其转换回Java枚举类型。

无论如何,我认为基于字符串的解决方案更加清晰、优雅,而且从长远来看更加安全(如果您需要更改Java枚举的顺序或在现有枚举中间添加新的枚举值,那么一开始采用基于字符串的策略会让您感到非常满意)。


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