SQL:避免硬编码或魔术数字

p.c*_*ell 19 sql t-sql stored-procedures

问题:在SQL脚本或存储过程中有哪些避免幻数或硬编码值的其他策略?

考虑一个存储过程,其作用是根据其StatusID或其他一些FK查找表或值范围来检查/更新记录的值.

考虑一个StatusID最重要的表,因为它是另一个表的FK:

替代文字

要避免使用的SQL脚本如下:

DECLARE  @ACKNOWLEDGED tinyint

SELECT  @ACKNOWLEDGED = 3   --hardcoded BAD

UPDATE  SomeTable
SET     CurrentStatusID = @ACKNOWLEDGED
WHERE   ID = @SomeID
Run Code Online (Sandbox Code Playgroud)

这里的问题是这不是可移植的,并且明确地依赖于硬编码值.将此部署到具有标识插入的其他环境时,存在细微的缺陷.

还试图避免SELECT基于状态的文本描述/名称:

UPDATE  SomeTable
SET     CurrentStatusID = (SELECT ID FROM [Status] WHERE [Name] = 'Acknowledged')
WHERE   ID = @SomeID
Run Code Online (Sandbox Code Playgroud)

问题:在SQL脚本或存储过程中有哪些避免幻数或硬编码值的其他策略?

关于如何实现这一目标的其他一些想法:

  • 添加一个新bit列(命名为'IsAcknowledged')和一组规则,其中只有一行的值为1.这有助于找到唯一的行:SELECT ID FROM [Status] WHERE [IsAcknowledged] = 1)

Phi*_*ley 12

对于像状态表这样的情况,我创建了所谓的"静态"数据集.这些表包含数据

  • 在创建时设置和定义,
  • 永远不会改变,和
  • 从数据库实例到数据库实例总是一样的,没有例外

也就是说,在创建表的同时,也使用脚本填充表,以确保值始终相同.此后,无论数据库在何处或何时,您都将知道这些值是什么,并且可以相应地进行相应的硬编码.(在这些情况下,我永远不会使用代理键或标识列属性.)

您不必使用数字,您可以使用字符串 - 或二进制文件或日期,或任何最简单,最简单和最合适的.(当我可以的时候,我使用char字符串 - 而不是varchars - 例如"RCVD","DLVR","ACKN"等等,比0,2和3更容易编码硬编码值.)

该系统适用于不可扩展的值集.如果可以修改这些值(这样0不再意味着"已确认"),那么您就会遇到安全访问问题.如果您的系统中有用户可以添加新代码,那么您有一个不同且棘手的设计问题需要解决.


dev*_*vio 10

我最近发现魔术数字可以通过视图实现:

CREATE VIEW V_Execution_State AS
SELECT 10 AS Pending, 20 AS Running, 30 AS Done

DECLARE @state INT
SELECT @state = Pending FROM V_Execution_State
Run Code Online (Sandbox Code Playgroud)

  • 但是,这种方法的一个问题是,如果您决定添加另一个执行状态,您现在不仅要更改视图,而且还会影响依赖于静态结构的任何代码. (2认同)

Ada*_*son 7

在某种程度上,会有一些"硬编码"的价值观.消除它们的想法来自两个方面:

  1. 使代码更易读(即说'Acknowledged',而不是3可能将会使你的意图更为明显给读者.
  2. 使代码更具动态性,其中一个函数可以采用参数而不是几个函数而不采用(这显然是一种简化,但其意义应该是相当不言而喻的)

bit为各种状态制作列可能是一个好主意或坏主意; 它真的只取决于数据.如果数据经过不同的"阶段"(收稿时承认,在审查,拒绝,接受,回应道,等),那么这种做法迅速扩展自身出活力(更不用说具有刺激性的过程,以确保只有一个的在任何给定时间将列设置为1).另一方面,如果状态真的像您描述的那样简单,那么这样做可以使代码更具可读性,索引性能更好.

硬编码值中最大的禁忌值是引用其他实体的硬编码值(换句话说,硬编码对应对象的主键).字符串'Acknowledged'仍然是一个硬编码的值,它的含义更透明,它不是对其他东西的引用.对我而言,归结为:如果你能(合理地)查找它,那就去做吧.如果您不能(或者从性能或可维护性的角度来看某些事情使其成为不合理的任务),那就硬编码吧.使用此方法,您可以使用以下方式查找值3 Acknowledged; 你无法Acknowledged从别的东西中抬起头来.