在数据库中存储枚举值

发布于 2024-11-09 19:59:24 字数 682 浏览 0 评论 0原文

仅供参考:我明确指的是 SQL Server 2000-8 和 C#。因此,像 MySql 这样具有枚举支持的 DBMS 不是我的问题的主题。

我知道这个问题已在 SO 中被问过多次。但是,我仍然在答案中看到采用不同的方法将枚举值存储在数据库中。

  1. 在数据库中将枚举保存为 int 并在代码中提取枚举值(或使用反射的枚举描述属性)
    这是我通常使用的方法。问题是当我尝试从 SSMS 中的数据库查询时,检索到的数据很难理解。

  2. 将枚​​举保存为数据库中的字符串(varchar)并在代码中转换回 int。
    事实上,这可能是最好的解决方案。但是(别笑!)感觉不对。我不确定缺点。 (除了数据库中的更多空间,这通常是可以接受的)那么还有什么反对这种方法的吗?

  3. 在数据库中有一个单独的表,该表与代码的枚举定义同步,并在主表和枚举表之间建立外键关系。
    问题是当稍后添加另一个枚举值时,代码和数据库都需要更新。另外,可能会有拼写错误,这可能会很痛苦!

因此,一般来说,当我们可以接受第二个解决方案中数据库的开销时,在数据库中存储枚举值的最佳方法是什么?是否有关于此的一般明确的设计模式规则?
谢谢。

FYI: I explicitly mean SQL Server 2000-8 and C#. So DBMSs with enum support like MySql is not the subject of my question.

I know this question has been asked multiple times in SO. But still, I see in answers that different approaches are taken to store enum values in db.

  1. Save enum as int in db and extract the enum value (or enum description attribute using reflection) in code:
    this is the approach I usually use. The problem is when I try to query from database in SSMS, the retrieved data is hard to understand.

  2. Save enum as string (varchar) in db and cast back to int in code.
    Actually, this might the best solution. But (don't laugh!) it doesn't feel right. I'm not sure about the cons. (Except more space in db which is usually acceptable) So anything else against this approach?

  3. Have a separate table in db which is synchronized with code's enum definition and make a foreign key relationship between your main table and the enum table.
    The problem is when another enum value should be added later, Both code and db need to get updated. Also, there might be typos which can be a pain!

So in general when we can accept the overhead on db in 2nd solution, What would be the best way to store enum values in db? Is there a general definite design pattern rule about this?
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

二货你真萌 2024-11-16 19:59:24

没有明确的设计规则(据我所知),但我更喜欢方法#1。

  1. 是我更喜欢的方法。它很简单,而且枚举通常足够紧凑,我开始记住数字的含义。
  2. 它更具可读性,但可能会妨碍您在需要时重构或重命名枚举值。您失去了代码的一些自由度。突然之间,您需要让 DBA 参与进来(取决于您在哪里/如何工作)只是为了更改枚举值,否则就会受苦。解析枚举也会对性能产生一些影响,因为诸如 Locale 之类的东西会发挥作用,但可能可以忽略不计。
  3. 这解决了什么问题?除非您想增加连接的开销,否则表中的某个位置仍然有不可读的数字。但有时,这也是正确的答案,具体取决于数据的使用方式。

编辑
克里斯在评论中提出了一个很好的观点:如果您确实采用数字方法,则应该显式分配值,以便也可以对它们重新排序。例如:

public enum Foo
{
     Bar = 1,
     Baz = 2,
     Cat = 9,
     //Etc...
}

There is no definite design rule (that I know of), but I prefer approach #1.

  1. Is the approach I prefer. It's simple, and enums are usually compact enough that I start remembers what the numbers mean.
  2. It's more readable, but can get in the way of refactoring or renaming your enumeration values when you want to. You lose some freedom of your code. All of the sudden you need to get a DBA involved (depending on where/how you work) just to change an enumeration value, or suffer with it. Parsing an enum has some performance impact as well since things like Locale come into play, but probably negligible.
  3. What problem does that solve? You still have unreadable numbers in a table somewhere, unless you want to add the overhead of a join. But sometimes, this is the correct answer too depending on how the data is used.

EDIT:
Chris in the comments had a good point: If you do go down the numeric approach, you should explicitly assign values so you can re-order them as well. For example:

public enum Foo
{
     Bar = 1,
     Baz = 2,
     Cat = 9,
     //Etc...
}
红尘作伴 2024-11-16 19:59:24

我之前见过的一个想法是你的选项3或多或少

  • 数据库中的表(用于外键等)
  • 客户端代码中匹配的枚举
  • 启动检查(通过数据库调用)以确保它们匹配

数据库表表可以有触发器或检查约束以降低更改风险。它不应该有任何写入权限,因为数据与客户端代码版本相关联,但它增加了一个安全因素,以防 DBA 崩溃。

如果您有其他客户端读取代码(这很常见),那么数据库已完成数据。

One idea I've seen before which is your option 3 more or less

  • A table in the database (for foreign keys etc)
  • A matching Enum in the client code
  • A startup check (via database call) to ensure they match

The database table table can have a trigger or check constraint to reduce risk of changes. It shouldn't have any write permissions because the data is tied to a client code release, but it adds a safety factor in case the DBA bollixes up

If you have other clients reading the code (which is very common) then the database has complete data.

弥繁 2024-11-16 19:59:24

我参考了这里的答案以及这个 问题。我想总结一下这些答案并添加我的观点。所以,这就是我的想法,

选项 1:将 Enum 值存储在查找表中,但不在代码中声明 Enum

  • 在此选项中,您将 Enum 值存储在查找表中并使用其主键作为其他表中的外键。
  • 当您希望“Enum”值是动态的并且可由用户在运行时修改时,请使用此选项。
  • 在此选项中,您的代码是完全动态的,并且不关心“Enum”值。

选项 2:将 Enum 值存储在查找表中,并在代码中声明 Enum

  • 与选项 1 类似,您也可以在此处创建一个查找表,但这次您还可以在代码中为其声明一个 Enum。
  • 当您的业务逻辑需要访问枚举值但您还想在数据库中提供引用完整性或者您打算将数据库与其他应用程序一起使用(例如数据分析)时,请使用此选项。
  • 在这里,您需要在应用程序启动时进行数据完整性检查,以确保代码中的 Enum 值与数据库中的 Enum 值同步。
  • 您需要决定哪一个应被视为数据库和代码之间的“真相来源”,并基于此执行同步。
  • 正如一些用户提到的,此方法还具有连接开销。

选项 3:在代码中声明 Enum,但不为其创建查找表

  • 在这里,您在代码中声明 Enum 并直接将 Enum 值插入到其他表中,而不是使用查找表的主表钥匙。
  • 当您的业务逻辑需要访问枚举值并且您不打算将数据库与其他应用程序一起使用时,请使用此选项。 (如果您打算这样做,请选择选项 2)
  • 您可以将 Enum 值存储为整数或字符串(无论您喜欢哪种)。
  • 这里您还需要一些基于业务逻辑的数据健全性检查。示例:如果从代码中删除 Enum 值,则任何记录都不应具有该 Enum 值。这些记录应该被删除或更新为适当的值。

I referred to the answers here and on this question. I would like to summarize these answers and also add my perspective. So, here's what I think,

Option 1: Store the Enum values in a lookup table, but don't declare Enum in code

  • In this option, you store the Enum values in a lookup table and use its Primary Key as a Foreign Key in other tables.
  • Use this option when you want your "Enum" values to be dynamic and modifiable by the users at run-time.
  • In this option, your code is completely dynamic and does not care about the "Enum" values.

Option 2: Store the Enum values in a lookup table and also declare Enum in code

  • Like option 1, here also you create a lookup table but this time you also declare an Enum for that in code.
  • Use this option when your business logic needs access to the Enum values but you would also like to provide referential integrity in the database or you intend to use the database with other applications also(ex. Data Analysis).
  • Here you require to keep Data Sanity checks on the application startup to ensure that the Enum values in the code and in the database are in sync.
  • You need to decide which one should be considered the "Source of Truth" between the database and the code and perform synchronization based on that.
  • This method also has a join overhead as mentioned by some users.

Option 3: Declare the Enum in code, but don't create a lookup table for it

  • Here, you declare the Enum in code and directly insert the Enum values in other tables instead of using the lookup table's primary key.
  • Use this option when your business logic needs access to the Enum values and you do not intend to use the database with other applications. (In case you intend to do so, prefer option 2).
  • You can store the Enum value as an integer or as a string (whichever you prefer).
  • Here also you need some Data Sanity checks based on business logic. Example: If an Enum value is deleted from the code, no records should have that Enum value. Those records should either be deleted or updated with appropriate values.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文