数据库设计 - 硬编码行ID

时间:2008-10-23 19:51:35

标签: database database-design

每个人都会将代码枚举与数据库表中的行ID联系起来?我真的在寻找更清洁的选择。例如,如果给定表中的静态行是ID的1,2,3,然后该表使用ID 4-100填充用户事务数据,然后您想在本地添加新的行ID生产数据库是行ID 4,但是当该行转到客户数据库时,它必须是101 ......这样就可以破坏所有内容。

那么如何在表中处理静态锁定行,这些行也会填充事务数据?

谢谢, MeshMan

10 个答案:

答案 0 :(得分:12)

不要那样做。 ; - )

如果你的静态行,永远不会改变的值,在具有事务性或至少是可变的用户数据的表中,那么我会说你在模式中至少有一个规范化问题。

参考数据通常属于它自己的表。如果表本身仅包含引用数据,则从应用程序分配ID或使用DB中生成的ID成为首选项。

我经常玩弄从DB表生成“源代码”Enum类或者在构建/部署时使用Enum类信息填充数据库表的想法,但我从来没有“理解它”。

答案 1 :(得分:1)

我同意Ken G - 对应于行ID的枚举值仅对具有静态(不变)内容的查找表有意义

答案 2 :(得分:1)

不要在应用程序中将特殊逻辑基于数据库中的行ID,特别是如果您无法完全控制该表中的内容。 (我承认我有时会为查询表执行此操作,我绝对不会知道这些更改,但即使在这里也可能是不好的做法。)

如果你需要标记某些特殊记录,那么请添加一些表示该标志的“flag”字段,然后查询该标志。

答案 3 :(得分:1)

我同意Stephen W.一个好的解决方案是使用ENUM项目的字符串name。我一直在.Net中使用这种方法,它很容易使用。

这个想法是,无论你的枚举有什么价值(并且无论数据库记录有什么ID),枚举名称只会在你的开发人员改变它时改变。与自动递增的ID号(在您的控制之外)相比,这是一种更易于管理的情况。另外,阅读代码的其他开发人员也知道名称试图描述的内容,而不是一些可能意味着什么的随机数字,并且可能意味着跨不同数据库的多个事物!

这可行的一种方法是让您的表具有文本代码或描述标识列。这可能是一个字母数字值,但关键是它应该唯一地标识该记录。实际上,这可以用作主键,但实际上我总是有一个自动递增的主ID号列。这样一个表上的列示例:

PK_ID | CODE | Other Data等。

这里,代码字段的值实际上是您的枚举名称。这是一个不需要更改的代码。你必须在你自己和你的团队中规定这些不要改变的规则,但是如果有人需要改变它,那么确保它反映在两个平台上。

使用.Net处理Enum(在本例中称为SortDirection):

' Get the string name of an enum
[Enum].GetName(GetType(SortDirection), SortDirection.Ascending)

' Get the enum value from its string name
CType([Enum].Parse(GetType(SortDirection), "Ascending"), SortDirection)

它不是一个完美的解决方案,但它对我很有帮助;我已经被硬编码的ID太多次困惑和烦恼,以至于不能更好地理解这两个邪恶。希望有所帮助!

答案 4 :(得分:0)

也许您可以发布一个示例来帮助我们更好地理解,但如果您有一些被指定为“系统”条目的行,您可以考虑在名为Order的表中添加一列,然后在创建一个条目时被设计为系统条目,您可以增加Order列。

对于大多数其他内容,例如查找表,您应该能够更明确地控制行ID并使用它们。

答案 5 :(得分:0)

嗯,一个枚举应该是一个常数 - 你不希望改变的东西 - 你真的不能说这个数据来自数据库。

无论如何,你的问题来自你从ENUM文本背后的INTEGER保存/加载的事实。一个有用的解决方案是从枚举的TEXT值进行查找/保存/等

这个VB代码将字符串转换回ENUM,它应该很容易移植到C#:

[Enum].Parse(System.Type, Value)

答案 6 :(得分:0)

这是一个解决方案:大多数数据库都有一种机制来生成新的ID值,从1开始向正方向递增。

但是,如果主键列是有符号整数,则可以对静态行使用负值。 ID为-1表示'--NONE--',ID为-2表示'--SPECIAL--'或其他。如果您需要更多静态行,请向负方向前进。

如果外键也是有符号整数,那么外键仍然可以引用静态行和用户生成的行。

答案 7 :(得分:0)

永远不应存储ROWID,因为它们可以更改。如果您将其中一个表移动到新的表空间,则所有存储的ROWID都将变为无效(无论如何,这在Oracle中都是如此)。

如果您有一个需要保护的FK特殊行,您可以使用触发器来阻止它被更新。

答案 8 :(得分:0)

不判断您的计划的合理性。 DBA和其他人总是喜欢说,“ 不要这样做。“好像你问你是否应该这样做,即使你没有问过,就像你可以选择不这样做。

我会假设你问了一个问题,并且你没有选择不这样做。

我有friend认为Oracle序列很痛苦,自动编号字段更容易。它们并不“简单”,但它们更灵活。到目前为止,您尚未说明您的平台,所以请不要使用mod -1。

在Oracle中,您可以创建序列以填充自动编号字段。序列完全独立于表格。您可以在多个表中使用一个序列,您可以在一个表中使用多个序列。如果我必须解决你的情况,我会创建2个序列,一个从1开始,一步一步(对于管理数据),一个从2开始,逐步2(对于用户数据)。我将更改我的插入过程以使管理插入的选项参数拉出正确的序列。您永远不会碰撞您的数据和用户数据。基于ID的奇偶校验能够区分两者的副作用。缺点是存在硬限制。

答案 9 :(得分:0)

我必须先在状态表上执行此操作。安装应用程序时必须始终存在某些“内置”值,并在特定时间点进行特殊处理。

然后,用户可以出于工作流原因创建自己的功能。

你能做的就是在1,001开始你的序列。 1到1,000之间的任何值都是“内置”值。当然,这里1000是一个神奇的数字,但在我的情况下,我只有5个内置值,所以看起来很安全。

另一个选项是用户创建的大于零的ids,系统内置的小于零。