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)
在某种程度上,会有一些"硬编码"的价值观.消除它们的想法来自两个方面:
'Acknowledged',而不是3被可能将会使你的意图更为明显给读者.bit为各种状态制作列可能是一个好主意或坏主意; 它真的只取决于数据.如果数据经过不同的"阶段"(收稿时承认,在审查,拒绝,接受,回应道,等),那么这种做法迅速扩展自身出活力(更不用说具有刺激性的过程,以确保只有一个的在任何给定时间将列设置为1).另一方面,如果状态真的像您描述的那样简单,那么这样做可以使代码更具可读性,索引性能更好.
硬编码值中最大的禁忌值是引用其他实体的硬编码值(换句话说,硬编码对应对象的主键).字符串'Acknowledged'仍然是一个硬编码的值,它的含义更透明,它不是对其他东西的引用.对我而言,归结为:如果你能(合理地)查找它,那就去做吧.如果您不能(或者从性能或可维护性的角度来看某些事情使其成为不合理的任务),那就硬编码吧.使用此方法,您可以使用以下方式查找值3 Acknowledged; 你无法Acknowledged从别的东西中抬起头来.