在 SQL Server 中管理/使用常量值

问题描述

sql 中的固定值或很少更改的值 - 如何最好地对其进行编码?

昨天写了一些 sql 代码,我正要在我的代码中输入一些固定的常量值(讽刺地通常称为“幻数”)。每次这样做,我都会感到一阵内疚。这就像故意制造技术债务,因为你只知道你正在为未来的问题提供“StatusX = 6 在我们的系统中有多少地方重要?” / “如果我们添加一个状态值,系统可能会在哪里中断或需要更改?

回答这个“在哪里使用”的问题总是一个寻宝游戏,因为有时直接使用固定值(StatusX = 6),有时在 IN 子句中使用 Status X IN (2,6,7),有时在范围内StatusX

解决方案:固定价值视图

搜索了这个,并特别找到了两篇文章(请参阅下面的链接 - 其中一篇在这里,在 StackOverflow 上)建议为此使用具有固定值的 sql 视图。起初我忽略了这个想法。它并没有立即引起我的注意,但是在查看了所提供的方法及其缺点之后,然后又发现了几次这个概念,我重新访问了它。经过仔细审查,我发现这种方法很有意义,而且有很多好处,而且在性能方面成本几乎为零。

这种方法最适用的场景是有一组固定值,通常存储在代码表中。这些值通常具有外键约束,以确保相关数据结构仅使用有效和/或活动代码值。传统 RI 涵盖数据的有效性,但它并没有使管理或编写使用位于这些大部分静态表中的代码值的 sql 代码变得更容易。这就是这些固定值视图的用武之地!

在这里重新发布这个想法,因为我认为它有很多优点,并且可以或应该被许多人使用。很高兴分享和听到它的任何改进或变化。我还在改进其代码友好性的想法中添加了一些(字面意思 - 见下文)。

好处

使用此方法,您可以使用 sql Server 的依赖项信息来检测这些固定值视图公开的固定值已被使用的位置。如果您确实需要添加一个值,这很容易,而且您很快就会知道应该在哪里检查使用情况。如果你想喘息删除一个值,你可以告诉它会破坏什么代码,因为视图会被修改。总而言之,这个想法对我很有吸引力。每次我用这种方法编码一个固定值时,我的大脑并没有感觉有点脏。

这种方法并不建议您没有实际的代码表,或者使用这些视图代替它们。最好有定义的代码表,并从使用它们的表中强制执行参照完整性。下面讨论的常量视图真正闪耀的地方在于 sql 编码:在函数、存储过程等中。

示例视图

CREATE VIEW dbo.cvw_OrderStatusID AS 
SELECT 
 CAST(1 AS bit) AS [Match Exists]   <-- Helper column for Left Outer Joins to check for record presence.,CAST(1 AS INT) AS [Draft],CAST(2 AS INT) AS [New],CAST(3 AS INT) AS [Open],CAST(4 AS INT) AS [Delivered]

基本用法

这是一个查询示例,用于查找处于仍应允许对其进行编辑的状态的订单:

-- Use Inner Join to select 1 to n values
SELECT
  O.OrderNumber,O.CustomerNumber
FROM
dbo.Order O
  INNER JOIN dbo.cvw_OrderStatusID OS_AllowEdit ON O.OrderStatusID 
  IN (OS_AllowEdit.[Draft],OS_AllowEdit.[New],OS_AllowEdit.[Open])

-- Use Cross Apply to pass a fixed value to a TVF for example:
SELECT orders.* FROM dbo.cvw_OrderTypeID OrderTypes
CROSS APPLY dbo.fn_Getorders(OrderTypes.[Express],@this,@that,@theother) orders
ORDER BY orders.DateSold

想法的小改进 - [Match Exists]

为了在检查匹配项的多个值时更明显或更容易测试,请将名为 [Match Exists] 的字段添加到类型为 Bit Default 1 (true) 的常量视图中。

当您使用 sql 常量视图时,您可以在数据必须匹配的地方使用 INNER JOIN,或者在数据可能匹配或不匹配 X 个不同值的地方使用 LEFT OUTER JOIN,像这样构建您的 sql

SELECT
  IIF(OS_OrderDelivered.[Match Exists] = 1,p.DeliveredDate,NULL)  AS OrderDeliveryDate,ISNULL(OS_AllowEdit.[Match Exists],0) AS AllowEditing
FROM
dbo.Order O
  LEFT OUTER JOIN dbo.cvw_OrderStatusID OS_OrderDelivered ON O.OrderStatusID = OS_OrderDelivered.[Delivered]
  LEFT OUTER JOIN dbo.cvw_OrderStatusID OS_AllowEdit ON O.OrderStatusID 
  IN (OS_AllowEdit.[Draft],OS_AllowEdit.[Open])

在到期时给予信用:

有关完整处理,请阅读这些博客,因为它们更深入地探讨了性能问题。

https://docs.microsoft.com/en-us/archive/blogs/sql_server_appendix_z/sql-server-variables-parameters-or-literals-or-constants

https://www.red-gate.com/hub/product-learning/sql-prompt/misuse-scalar-user-defined-function-constant-pe017

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)