更改架构后如何检测损坏的存储过程?


11

我已经在数据库中修改了一个中央表,并且sp_depends确实返回了数百个结果,而且我担心其中的一些存储过程在更改后可能无法再编译。

检查一个存储过程很容易(我只是重新运行alter脚本,然后查看操作是否成功),但是在100多个过程中执行此操作比较麻烦。

我知道我可以使用像这样的脚本来重新编译数据库中的所有对象,但是实际操作将在下一次执行存储过程时发生,而不是立即执行,因此对于我来说似乎不合适。

我还以为我可以完全删除所有存储过程,并使用源代码控制系统重新同步数据库,但是该选项虽然可行,但却不是一个很好的选择。有更好的方法吗?

我正在使用SQLServer 2008 R2,我的数据库脚本存储在VS 2008数据库项目中。


需要澄清的是,我并不是在主张应该完全依靠这种方法来测试代码。就像在C#中一样,您在编写代码时会立即检测其他依赖文件中的语法错误(然后使用其他策略进行测试,例如单元测试,通常速度要慢几个数量级),我认为检测SQL依赖关系很有意义错误只需几秒钟即可完成,而不必运行通常需要几个小时才能完成的完整功能测试。

Answers:


7

您如何进行单元,功能,集成和性能测试?如果您没有任何测试,那么是非常认真的时间,开始将数据库架构视为代码并将其视为代码,包括版本控制和测试。亚历克斯·库兹涅佐夫(Alex Kuznetsov)有一本专门针对该主题的整本书:《使用SQL Server进行防御性数据库编程》


测试并不总是覆盖100%的代码,而测试通常要花几个小时才能运行。在c#中,我可以检测我的代码是否仍在几秒钟内编译(不管它是否正确)。这并不意味着我应该在没有正确测试的情况下就将代码(无论代码是c#还是PLSQL)推入生产环境,但是似乎没有一种能够快速检测到破坏的依赖关系的方法,这是不合理的吗?
布兰恩

2
不幸的是,相对于存储过程中的依赖关系检测,SQL Server目前的最新技术已“被严重破坏”,请参阅SQL Server 2008中的了解SQL依赖关系保持系统依赖关系最新。甚至还有第三方工具试图解决该问题
Remus Rusanu 2012年

2
这使得单元/功能测试几乎是检测重大变化的唯一可靠方法。
Remus Rusanu'4

1
为了快速检查,Visual Studio数据库项目在验证任何更改方面做得相当不错。
Remus Rusanu'4

4

这是一个变通方法,但是您可以为数据库生成CREATE PROCEDURE脚本(右键单击数据库->任务->生成脚本),找到并用ALTER PROCEDURE替换CREATE PROCEDURE,然后进行解析。

希望您在这里得到更好的答案-我也很感兴趣!:)


我并未将您的答案标记为接受,因为我仍然希望有一个更干净的解决方案(希望是一个可编写脚本的解决方案),但您肯定会得到我的+1!谢谢。
布兰恩

3
如果您要引用不存在的表,这种方法不会让您知道。
Nick Chammas

如果生成的脚本大于大约30k行,则此方法也将不起作用。我讨厌我知道这一点
。– Eonasdan

3

您可以使用Sql Server数据工具(SSDT)。Microsoft Visual Studio允许您创建Sql Server项目。然后将数据库导入到项目中,然后构建项目。如果有任何损坏的存储过程或对象,则会出现编译错误。


我要补充一点,您可以轻松地从SSDT项目中生成一个新的数据库创建脚本并在测试环境中运行,这将是一个非常彻底的验证,确认没有因架构更改而导致procs / triggers / etc损坏。
AaronLS

3

您可能想看看这个SO问题,我正在寻找一种可靠的方式来验证T-SQL存储过程。有人得到吗?基本上是同一件事,有几个答案。

要基于Alaa Awad发布的脚本...,这应该显示引用和引用对象的模式和数据库。如果您通过别名使用许多临时表(使用时有时会显示这些表sys.sql_expression_dependencies),UDTT参数或其他动态功能,则可能需要使用这些功能,sys.dm_sql_referenced_entities或者sys.dm_sql_referencing_entities也可以使用这些功能。

SELECT
    DB_NAME() + '.' + OBJECT_SCHEMA_NAME(sed.referencing_id) + '.' + OBJECT_NAME(sed.referencing_id) AS [referencingObject],
    isnull(sed.referenced_server_name + '.', '') + isnull(sed.referenced_database_name + '.', DB_NAME() + '.') + isnull(sed.referenced_schema_name + '.', OBJECT_SCHEMA_NAME(sed.referencing_id) + '.') + sed.referenced_entity_name AS [missingReference]
FROM 
    sys.sql_expression_dependencies sed
WHERE 
    sed.is_ambiguous = 0
    AND OBJECT_ID(isnull(sed.referenced_database_name + '.', DB_NAME() + '.') + isnull(sed.referenced_schema_name + '.', OBJECT_SCHEMA_NAME(sed.referencing_id) + '.') + sed.referenced_entity_name) IS NULL
ORDER BY
    [referencingObject], [missingReference]

1
应该将这些添加到where子句中:/ *不是现有的用户类型/ AND sed.referenced_entity_name NOT IN(从sys.types中选择[name])/不是别名* / AND sed.referenced_schema_name IS NOT NULL
JasonBluefire

1

使用SQL Server 2008中添加的sys.sql_expression_dependencies

CREATE PROCEDURE [dbo].[spMaintenance_Find_Broken_Dependencies]

AS
SELECT
    OBJECT_NAME(referencing_id) AS [referencingObject],
    referenced_entity_name AS [missingReference]
FROM 
    sys.sql_expression_dependencies
WHERE 
    is_ambiguous = 0
    AND OBJECT_ID(referenced_entity_name) IS NULL
ORDER BY 
    OBJECT_NAME(referencing_id), referenced_entity_name

GO

这可能很有用,但是并不是那么简单,因为还需要考虑架构。我还遇到sys.sql_expession_dependencies显示使用的别名而不是实际的依赖表的问题,这显然使object_id()测试失败。最后,它带来了用户定义的表,这些表作为参数传递给存储过程-并没有真正的用处。
Tabloo Quijico 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.