7

我正在使用 Orable 数据库,并且正在添加几个查找表。

一般的问题是查找表是否应该包含代码和描述并且代码是返回到主表的 FK,或者查找表是否应该只包含描述并且是返回到主表的 FK。

我在争论代码/描述对。我觉得如果我有type = Contractor一个code = CN存储过程应该说where type='CN'而不是只有type=Contractor没有代码并在存储过程中说这个:where type='Contractor'因为如果我想显示:General Contractor给用户而不是Contractor. 然后我将不得不更改存储过程。我觉得我不应该这样做。(更改存储过程需要在开发中重新编译,迁移到测试,由客户端重新测试,以及迁移需要经过更改控制过程的产品,这需要两周的等待期;而修改表中的记录不需要任何这个的)

我的数据建模者只想使用描述。他的主要论点是它需要一个不必要的连接。

应该采用哪种方式?如果应该以代码/描述方式完成,我如何说服数据建模者?

谢谢!

type_cd    type_dsc
CN         Contractor
IN         Inspector
4

8 回答 8

13

总结所有答案,我认为查找表有四种选择:

备选方案 1:
• 说明(主键,较长的 varchar2 列)

备选方案 2:
• 代码(主键,短 varchar2 列)
• 描述(非空,更长的 varchar2 列)

备选方案 3:
• Id(无意义的主键,从序列派生的整数值)
• 描述(非空,更长的 varchar2 列)

备选方案 4:
• Id(无意义的主键,从序列派生的整数值)
• 代码(唯一键,短 varchar2 列)
• 描述(非空,较长的 varchar2 列)

主键列将位于主表中,顶部有外键约束。

每个替代方案的一些特征:

备选方案 1:
• 查询主表时不需要连接
• 对主表执行即席查询时含义明确
• 主表需要更多存储空间
• 主表上的索引将比其他备选方案大得多
• 更新描述值意味着维护麻烦和可能的应用程序停机时间。

备选方案 2:
• 当您想要检索描述值时
需要加入 • 如果您想要过滤某些查找值,则不需要加入:您可以为此使用代码值。
• 对主表进行即席查询时非常明确的含义 • 对主表
的附加存储要求最低
• 主表上的索引会很小。
• 更新描述值很容易,但是代码通常是描述的缩写。更新描述值时,代码可能会变得混乱。

备选方案 3:
• 当您想要检索描述值时需要加入
• 当过滤某些查找值时,您必须在查询中使用描述值,因为 Id 没有意义。
• 对主表进行即席查询时含义不明确 • 对主表
的附加存储要求最低
• 主表上的索引会很小。
• 更新描述值很容易,不会像代码值那样引起混淆

备选方案 4:
• 当您要检索描述值时
需要连接 • 当过滤某些查找值时需要连接,您将使用查找表中的代码值。
• 对主表进行临时查询时,含义不清楚 • 对主表
的附加存储要求最低
• 主表上的索引会很小
• 更新描述值很容易,您也可以非常轻松地将代码值更新为使其类似于描述值。但是,在执行此操作时,您可能需要重新访问一些代码。

个人意见:

我会看看我打算如何使用主表和查找表。哪些查询很重要并且必须高效运行?价值观会改变吗?

我个人的选择是备选方案 2 或 4。如果我绝对确定代码值永远不会改变,我会使用备选方案 2。这是罕见的。国家代码改变,社会安全号码改变。货币代码更改等。所以,大多数时候,我会选择备选方案 4。我不会那么担心额外的连接,尤其是因为查找表是一个小表。

但是:选择适合您要求的替代方案。

当您了解替代品的更多特征时,请随时编辑文本。

问候,
罗布。

于 2011-02-10T13:25:19.527 回答
5

代码/说明。该代码值(我假设)将是一个更小、更有效的整数。此外,您不希望仅仅因为文本描述在未来某个时间发生更改而需要更新所有外键。

编辑:根据您刚刚添加的示例代码,我鼓励您将代码值设为整数值,而不是像“CN”、“IN”这样的字符串。您希望您的键值与描述相关的任何“含义”无关。“CN”仍然意味着“承包商”,如果/当该描述更改为“外部资源”时,“CN”将具有误导性。

于 2011-02-09T14:38:13.493 回答
4

好吧,这将取决于这些代码的“标准”程度。

考虑一个像这样的查找表:

Code  Description
------------------
USD   United States Dollar
GBP   Pound Sterling
AUD   Australian Dollar
EUR   Euro

为此,我将使用char(3)forCode并使其成为主键。您的代码似乎是 char(2) - 整洁、小巧;小于整数。

所以我的猜测是Code在查找表中使用 PK,而“主表”将Code作为查找表的 FK。

如果您的代码不是很标准并且可能会更改,则首选整数。

于 2011-02-09T15:43:59.087 回答
4

很多事情都有现有的标准和编码方案,这些都是被认为是比我更聪明并且有更多时间思考的人。例如,ISO 标准涵盖性别代码 (iso 5218)、国家代码 (iso 3166)、语言代码 (iso 639)、货币代码 (iso 4217) 等等。去年我购买了Joe Celko 的 SQL 中的数据、测量和标准,我真的很惊讶有多少官方维护的现成标准和编码方案。

好吧好吧,所以偶尔有些国家放弃他们的香蕉而支持欧元/美元,现在你必须重写你的整个应用程序?不,您必须花几个小时编写脚本来合并/拆分任何更改的代码。大不了。为什么不在同一个版本中修复一些错误呢?

就我个人而言,我几乎所有必须编写代码的东西都使用短字符代码,或者当我需要根据某些“类型代码”分配行为时。代码与类型代码如此紧密地联系在一起,那么为什么要让它变得更难呢?生成的代码更容易阅读,并且执行得更快,因为我需要更少的连接。对于其他所有内容(基本上都是用户生成的),我使用整数代理。

我已经“只”使用数据库 11 年,但我还没有看到很多“名称更改”如此显着以至于代码变得误导的情况。“承包商”的类型代码,不能更改为“人力资源经理”或“副总裁”。那是一个新的代码。它可能会拆分为“内部/外部资源”,但这也需要更改代码,在这种情况下,我认为在项目预算中增加几个小时的数据转换不会有问题?

最后,在某些时候,您必须承诺您在代码中输入的值。你可以使用任何你想要的值,但它仍然意味着同样的事情

我看过以下所有内容:

where type = 1 /* contractor */ 
  vs

int type_code = configfile.lookup("sqlcodes.contractor");
...
where type = :type_code
  vs

 from sometable
 join contract_types using(type_id)
where contract_types.type_name = 'Contractor';

...但我仍然没有看到这样做的好处:

where type = 'CN'

我想说的是:当我们花费 80 小时进行开发时,4 小时的数据库活动怎么会不符合项目预算呢?

于 2011-02-09T22:48:18.410 回答
2

使用数字 id 值和描述。将 id 作为 FK 存储在主表中。

字符串是糟糕的 FK 值,基本规范化会告诉您的数据建模者,您希望灵活地在查找表中更改一次字符串,而不必在引用它的任何地方更改它。

于 2011-02-09T14:38:18.570 回答
2

使用永远不会更改的助记符(例如,承包商的 CN 等)。让 UI 显示描述。一个小的代码表可能适合一两个块,因此通常会在缓存中找到,因此查找成本很低​​。

最重要的是,未来的开发人员和后来必须将这些数据映射到其他系统的人(比如我)会感谢你,因为这意味着 80% 的时间你可以只查询表并直观地理解它。

当我看到这样的桌子时,我只想尖叫:

ADDRESS_ID
HOUSE_NUMBER
STREET_NAME
STREET_TYPE_ID
LOCALITY_ID

SELECT * FROM addresses WHERE street_type_id = 10053;

代码永远不必更改(它们在系统内部,最终用户不应该看到它们)。描述有时会发生变化,但通常不会变化很大。根据我的经验,描述变化如此之大以至于助记符不再有意义的情况非常罕见。

于 2011-02-10T05:04:43.067 回答
1

看,取决于键分布 - 对于大多数小型查找表,任何加入它的查询都将对查找和哈希连接键进行全表扫描 - 所以数字与字符可能完全不是性能问题加入。

问题真的是 - 你需要加入吗?

我的意思是 - 如果您正在存储查找以用作 UI 的显示值,那么可以使用查找并加入它,以便您可以轻松更新显示值。

另一方面,如果您正在为多语言应用程序使用资源文件,并且您正在使用返回的代码作为查找,并且它是一小组预计不会更改的代码(Gender_Code = 'M'ale or ' F'emale 或 'U'nknown 例如) - 然后使代码有意义,在字段上使用检查约束来控制值,甚至不用查找表,因为您通过代码和 UI 知道它们将弄清楚如何显示它们。

于 2011-02-09T17:44:05.473 回答
0

我的建议是使用 int ID 和 char/varchar 描述。

在查询中使用 ID,并且仅在需要显示描述时链接到描述。

不用担心 ID 看起来不像描述。这是它应该工作的方式。您需要一个不重要的 ID,这样没人会猜到“CH”或“EX”等的含义。在代码中添加注释,解释 ID 的含义。

您希望能够在不破坏代码的情况下随时更改描述。您不想在所有代码更改时修复它们。

此外,您可以将一个或多个组添加到描述表中。如果您有多个承包商类型,您可以添加一个指示类型的组列。然后您可以链接到组描述表并返回组为 Contractor 的所有行。当然,该组应该有一个带有 ID 和描述的查找表,以便您可以更改查找组的显示名称。

告诉数据建模者您要将数据放入相关表中。这就是为什么它被称为关系数据库。

于 2011-02-09T20:06:05.650 回答