SQL 标识值硬编码的最佳实践

SQL Best Practices for Identity value hard coding

首先,我知道这是一个相当主观的问题,但我需要某种正式的文档来帮助我教育我的客户。

背景 - 具有数百个表和 SP 的大型企业应用程序,所有表和 SP 都经过精心设计,具有规范化的表和使用标识列的外键。

我们的客户有一些员工在 Crystal 企业中使用我们生产数据库的复制副本编写复杂的报告。

我们有存储我归类为 'system' 基本信息的表格,例如办公地点列表或公司内的部门、用户的标准角色集、其他对象的状态(open/closed等),基本上是不经常变化的数据。

问题 - 报表设计者和财务分析师正在编写其中包含硬编码标识值的查询。像这样

SELECT xxx FROM OFFICE WHERE OFFICE_ID = 6

我在这里大大简化了,但基本上他们在他们的程序中到处使用这些硬编码的 int 值。

对于 SQL 开发人员来说,看到这个显然会让你 facepalm 因为它只是一种不这样做的内在本能。

然而,令人惊讶的是,我找不到任何关于为什么不应该这样做的文档或最佳实践文章。

他们会争辩说这样做很好,因为这些值永远不会改变,而且他们是对的,在单个系统中这些值不会改变,但是在多个环境中 (staging/QA/Dev) 这些值可以并且完全不同,这使得他们的报告设计方法不可移植并且只能在 1 个隔离的服务器环境中运行。

SQL 大师是否有任何更深入的 information/articles 等我可以用来帮助教育我的客户为什么他们应该避免这种方法?

在我看来,对您的报告撰写者最有力的论据是您的倒数第二句话“......这些值可以而且是绝对不同的[在环境之间]”。这几乎就是我对他们的回应的要点。

当然,任何问题都存在灰色地带。标识列本质上是 magic numbers。他们对数据库的好处是...

  • 顺序
  • 快速搜索和加入、排序和创建

...但缺点是完全没有意义,实际上是随机分配的(以一种方式将插入内容排序为 table,与对另一种方式)。因此,在您必须查找类似特定内容的情况下,通常还包括一个 "business/natural/alternate" 键(例如,也许(一个完全虚构的示例)[CategoryName],其中 CatgoryName 是简短的、独特的和人类可读的,而 [CategoryId] 是一种身份,但不是旨在寻找的东西)

如果你的网站有一个下拉菜单,通常自然键会被放入下拉菜单的可见部分,而 surrogate/identity 键会在后端传递,不可见给最终用户。

当有人直接针对数据库编写查询时,这会变得有点棘手。如果他们是数据的所有者,他们可能会了解更大的数据结构,他们可以通过*咳嗽 "clever" 方式利用这些信息。如果您 知道 键不会改变并且您 知道 这些值是什么,那么可能会出现仅引用这些值的情况。但同样,如果您查询不同的服务器时它们会有所不同,则不会。

当然,另一方面是,如果您不希望他们使用身份值,则必须给他们一个替代方案。如果您的 table 还没有包含 business/natural/alternate 键,您将不得不在不存在的地方添加一个。

此外,备用键是整数也没有错(也许您已经拥有公司范围内的办公室标识符 1、2、3 等),但关键是无论您在哪里,它都是确定性的运行 您的查询。