将可为 null 的列传递给函数会导致警告 SR0007 - 即使该函数在内部使用 COALESCE 和 ISNULL

Passing Nullable Columns to a Function Causes Warning SR0007 - Even Though the Function uses COALESCE and ISNULL Inside

提问人:John Saunders 提问时间:1/27/2015 最后编辑:John Saunders 更新时间:1/28/2015 访问量:1706

问:

我有一个谓词,在许多不同的 WHERE 子句中重复,所以我“巧妙地”将其重构为标量值函数

CREATE FUNCTION dbo.IsCurrent
(
    @FromDate DATE,
    @ToDate DATE,
    @AsOfDate DATE
)
RETURNS INT
AS
BEGIN
    DECLARE @Today DATE;
    SET @Today = COALESCE(@AsOfDate, GETDATE());

    RETURN
         CASE
             WHEN @Today BETWEEN ISNULL(@FromDate,'1900-01-01') AND ISNULL(@ToDate, DATEADD(dd, 1, @Today))
             THEN 1
             ELSE 0
         END;
END

如您所见,该函数期望为任何参数传递 NULL 值,并正确处理它们。它将始终产生 1 或 0。

但是,当我调用该函数,将一个可为 null 的列作为参数之一传递时,我从代码分析中收到警告 SR0007:

SR0007:Microsoft.Rules.Data:可为 null 的列可能导致谓词的最终结果计算为 NULL。

我能做些什么来防止在调用此特定函数时出现这些警告?我采用了一条规则,即对我更改的任何代码都没有代码分析警告。我希望我不必仅仅为了让 SSDT 代码分析闭嘴而使用参数。有没有办法“给它一个提示”?ISNULL


当我说“给它一个提示”时,我在想 ReSharper 是如何做事的。您不仅可以控制哪些警告的严重性,还可以通过代码中的编译指示或注释禁用警告的特定实例,或者可以使用批注。例如,我可以在参数上添加注释,以指示它永远不会为 null。我希望会有类似的东西,或者具有相同效果的东西。[NotNull]

sql-server 代码分析 sql-server-data-tools

评论

0赞 Keith 1/28/2015
只是一个猜测 -- 如果将默认值添加到参数中是否有帮助?@FromDate DATE = NULL, ...
0赞 John Saunders 1/28/2015
@Keith:第一次尝试时,我无法让默认值在函数中工作。我仍然需要传递所有参数。
0赞 Keith 1/28/2015
恕我直言,SQL 函数中的默认参数是违反直觉的。调用函数时仍需要指定每个参数。但我希望这种方法能为代码分析提供你正在寻找的提示。

答:

4赞 Kevin Cunnane 1/28/2015 #1

您可以右键单击“错误列表”中的警告,然后选择“禁止显示静态代码分析消息”。这将禁止显示该特定文件中 SR0007 错误的所有情况。它仍然会在其他文件中引发(听起来像是你想要的)。或者,如果您不想看到这些警告,请在项目属性中禁用该规则。

编辑:发生的情况是创建一个名为StaticCodeAnalysis.SuppressMessages.xml的文件,其中包含以下条目:

<!-- language: lang-xml -->
<?xml version="1.0" encoding="utf-8" ?>
<StaticCodeAnalysis version="2" xmlns="urn:Microsoft.Data.Tools.Schema.StaticCodeAnalysis">
  <SuppressedFile FilePath="DatabaseScalarFunction1.sql">
    <SuppressedRule Category="Microsoft.Rules.Data" RuleId="SR0007" />
  </SuppressedFile>
</StaticCodeAnalysis>

如您所见,它首先按文件名过滤显示的错误/警告,然后按规则 ID 过滤。因此,文件“DatabaseScalarFunction1.sql”中 ID 为“SR0007”的任何警告都将被忽略。如果此文件中有多个过程,它将忽略所有过程的警告。

评论

0赞 John Saunders 1/28/2015
“在那个特定的文件中”是什么意思?你的意思是在整个存储过程中?这已经足够好用了,尽管我仍然会错过该存储过程中 SR0007 的任何合法案例。
1赞 Kevin Cunnane 1/28/2015
我添加了对发生的事情的解释 - 这确实意味着合法案例也被过滤掉了。如果要请求修复基础行为,我建议打开一个 Connect bug 来改进规则的行为 - 转到 connect.microsoft.com/SQLServer/feedback/CreateFeedback.aspx 并使用类别“开发人员工具(SSDT、BIDS 等)”。
0赞 John Saunders 1/28/2015
谢谢,凯文。顺便说一句,如果您在 Microsoft 工作,您可能希望在您的个人资料中这样说,作为披露问题。
1赞 Kevin Cunnane 1/28/2015
谢谢约翰,我没有意识到我错过了这些信息 - 现在已修复。