为什么SQL构建不验证明显的错误,我们如何实现自动验证?



在QA中通过手动用户测试意识到存在代码错误,经过调查,这是一个明显的错误。

CREATE PROCEDURE ProcedureA
@A INT
AS SELECT 1
GO
CREATE PROCEDURE ProcedureB
AS EXEC ProcedureA @B = 0

此外,手动执行这些CREATE语句不会引发任何错误。


另一个例子

CREATE VIEW VW_MyTestView AS
SELECT Column1 = 0
GO
CREATE PROCEDURE MyTestProcedure AS
SELECT Column1
FROM VW_MyTestView
GO
ALTER VIEW VW_MyTestView AS
SELECT Column2 = 0

修改对象时,它不会验证依赖项。


另一个骇人听闻的情况是FROM子句中列数不等的语句INSERT如下所示:

INSERT INTO MyTable(TheOnlyColumn)
SELECT
Column1 = ...
,Column2 = ...
,Column3 = ...

至少在更改/创建存储过程时会发现此问题。


另一个例子

CREATE PROCEDURE MyProcedure
@MyFlag BIT = 0
AS BEGIN
IF @MyFlag = 1
BEGIN
DECLARE @MyImportantVariable DATE = GETDATE()
END
EXEC MyOtherProcedureThatNeedsAnImportantValue
@MyImportantParameter = @MyImportantVariable
END

没有错误,当值@MyImportantVariable被引用时,它将被NULL,而不是遵循任何声明。在这种情况下,我实际上更希望抛出错误,因为调试一个令人惊讶的NULL值更加困难。


另一个类似于#1的例子,在过去一年中幸存了数千个门控TFS构建后,它让我脸上出现了一个鸡蛋:

CREATE PROCEDURE MyProcedure
@MyRequiredVariable INT--has no default
AS BEGIN
...
END
GO
EXEC MyProcedure--omits required parameter

为什么 MSBuild 进程没有捕获这样的东西,这显然是无效的,有没有办法为此类引用错误添加验证?我可以理解前两种情况在发布更改时是必要的,因为否则您将遇到无法刷新相互引用的定义的第 22 条军规,但第三种情况是没有意义的,永远无法接受,第四种情况甚至永远不会用 C# 这样的语言编译。

这也破坏了我们的门控签入构建验证过程。

发生这种情况是因为 SQL Server 存储过程的Deferred Name Resolution and Compilation属性。

如果它不是存储过程、函数、表或视图等,那么它在编译时就会出错。

但是,SQL Server 存储过程仅在创建时检查语法准确性,并且存储过程的定义按原样存储。

它仅在运行时,在第一次执行对象时 检查过程引用,如果缺少任何内容,该过程将引发错误。

相关内容

  • 没有找到相关文章

最新更新