在代码中引用自然和/或代理键值的最佳实践

时间:2013-02-01 20:22:52

标签: sql sql-server tsql

我正在修改一些在更新记录时管理状态更改的存储过程。

例如,如果我有这两个表

Request(RequestID, StatusID)
Status(StatusID, StatusName)

我正在努力确定最好处理代码中的状态。

我使用StatusID还是StatusName

无法保证StatusID在环境(DEV,PRE,PROD等)之间匹配。

此外,StatusName可以更改,我不想更改代码,因为我需要更改StatusName

我可以创建第二个唯一列,它类似于StatusID

我确保这个列在区域之间是匹配的,但这似乎也不干净,并且有点重复。

有人能建议更清洁,更简单的方法吗?

5 个答案:

答案 0 :(得分:2)

将代码与数据匹配的难度只能部分用第二列处理。当有人添加项目时,这意味着什么?如果他们重新使用已知常量,如果您不要求此列是唯一的,这意味着什么?

我们经常会有用户可修改的查找表,但是它们必须与许多其他标志相关联,这些标志指示如何解释状态 - “IsTreatedAsExpired”,“IsTreatedAsActive”或者其他可能保持状态的表。被视为某些事物。

我认为你真的需要首先弄清楚你想要允许的范围。因为如果您有很多代码引用,那么最好使用与所有安装中的代码同步的自然键。处理此问题的可能性是对不可移动的代码使用负数(标识插入以添加新的不可移动的代码),然后让您的序列只添加正数。但同样,这并没有解决程序如何处理或使用用户输入的扩展的语义。

同样,如果没有在这里整理范围,很难说。

答案 1 :(得分:1)

编写一个接受状态名称的用户定义函数,并在您提及状态ID的任何地方给出状态

select * from resources where statusid = dbo.getStatusId("COMPLETED");

这将确保解析状态ID始终发生在您定义的函数

答案 2 :(得分:1)

根据经验,当您拥有id,值表(状态,结果,区域等)时,我通常会添加第三个字段,该字段是记录的助记符值,并且始终使用该字段,无论是名称还是ID。 现在,助记符值就像一个业务键(好吧,它是一个业务键),因为它是一个业务值而不依赖于数据库(对于id)或它显示的方式(描述),例如您的状态表可能有

StatusID,StatusName,StatusMnemo
1       ,COMPLETED ,COM
2       ,REJETED   ,REJ

等等。

在您的查询中,您始终通过statusId加入,但是您添加一个子句以通过StatusMnemo加入状态表。这是一个在不同环境中独立的值,并且保持不变。

同样在插入中,您始终使用statusid。

答案 3 :(得分:1)

根据您提供的信息,StatusID可能在不同的数据库中具有不同的值,可能是因为您的密钥是自动生成的,并且未由您指定。如果是这样,那么显然无论如何都不可能在代码中始终使用StatusID(没有标准化值)。因此,在我的代码中对StatusName值进行硬编码是否可接受/实用/可取?"

明显的答案是肯定的,还有什么选择?如果您具有代表“准备就绪”的特定状态。并且您想在代码中引用它,那么您必须在代码中放置某些,以明确地标识状态。

如果添加某种类型的第二个密钥(如Carlos建议的那样),您仍然遇到相同的基本问题,即更改自然密钥值会更改状态的标识,从而更改代码的含义。如果你改变了真实的'自然键(READY)在不更改第二个键(RDY)的情况下,您的代码将变得更加混乱且难以维护。

如果你做了更复杂的事情,比如提取常数'或者'配置参数'在配置文件或表中甚至编写自定义预处理器以在部署时将键值插入到脚本中时,您会增加很多复杂性以获得非常小的收益(除非您有其他充分的理由这样做)。我已经看过这种方法,这是一个巨大的,无法维护的混乱。

在实践中,StatusName最有可能发生变化,因为a)有人认为其他名称会更加准确。或者“看起来更好”,或者b)您发现它并没有正确代表您的要求。如果您被迫花费时间a),那么只需更改前端的显示名称或报告并单独保留数据库和代码。如果b)出现,那么根据定义,您当前的数据模型和代码是不准确的,必须修改并可能进行修改。当b)确实发生时,通常会导致添加新代码,而不是更改现有代码(例如,因为有人定义了一个新的流程步骤,没有现有代码)。

如果您愿意改变您的开发和部署实践,还有其他方法可以查看此问题,正如其他人所建议的那样。你能在任何地方使你的StatusID价值相同吗?从技术上讲,它是可能的,那么组织原因是什么?您是否可以通过变更管理和代码审查来降低StatusName更改的可能性和影响?您是否可以改进您的需求流程以更有效地捕获某些信息?

答案 4 :(得分:0)

如果您的statusID值需要特殊处理,那么它们在不同环境中应该是相同的 为什么你会介绍一个需要在Prod中进行特殊处理的statusID,它还没有通过Pre和Dev?

我经常做的是在100开始识别,并将其用于不需要特殊处理的通用状态。

然后DEV拥有100以下的空间,使用IDENTITY INSERT ON进行特殊处理。

如果从DEV部署到PRE,则插入100以下的任何记录。