语法检查所有存储过程?

Ian*_*oyd 18 sql-server maintenance stored-procedures

我想确保所有存储过程仍然在语法上有效.(如果有人重命名/删除表/列,就会发生这种情况).

现在我检查所有存储过程语法的解决方案是进入企业管理器,选择列表中的第一个存储过程,并使用以下过程:

  1. 输入
  2. Alt + C键
  3. 逃逸
  4. 逃逸
  5. 向下箭头
  6. 转到1

它有效,但它非常繁琐.我想要一个名为的存储过程

SyntaxCheckAllStoredProcedures

就像我写的其他存储过程对视图做同样的事情:

RefreshAllViews


为了每个人的利益,RefreshAllViews:

RefreshAllViews.prc

CREATE PROCEDURE dbo.RefreshAllViews AS

-- This sp will refresh all views in the catalog. 
--     It enumerates all views, and runs sp_refreshview for each of them

DECLARE abc CURSOR FOR
     SELECT TABLE_NAME AS ViewName
     FROM INFORMATION_SCHEMA.VIEWS
OPEN abc

DECLARE @ViewName varchar(128)

-- Build select string
DECLARE @SQLString nvarchar(2048)

FETCH NEXT FROM abc 
INTO @ViewName
WHILE @@FETCH_STATUS = 0 
BEGIN
    SET @SQLString = 'EXECUTE sp_RefreshView '+@ViewName
    PRINT @SQLString
    EXECUTE sp_ExecuteSQL @SQLString

    FETCH NEXT FROM abc
    INTO @ViewName
END
CLOSE abc
DEALLOCATE abc
Run Code Online (Sandbox Code Playgroud)

为了每个人的利益,一个存储过程将所有存储过程标记为需要重新编译(标记存储过程以进行重新编译不会告诉您它是否在语法上有效):

RecompileAllStoredProcedures.prc

CREATE PROCEDURE dbo.RecompileAllStoredProcedures AS

DECLARE abc CURSOR FOR
     SELECT ROUTINE_NAME
     FROM INFORMATION_SCHEMA.routines
    WHERE ROUTINE_TYPE = 'PROCEDURE'
OPEN abc

DECLARE @RoutineName varchar(128)

-- Build select string once 
DECLARE @SQLString nvarchar(2048)

FETCH NEXT FROM abc 
INTO @RoutineName
WHILE @@FETCH_STATUS = 0 
BEGIN
    SET @SQLString = 'EXECUTE sp_recompile '+@RoutineName
    PRINT @SQLString
    EXECUTE sp_ExecuteSQL @SQLString

    FETCH NEXT FROM abc
    INTO @RoutineName
END
CLOSE abc
DEALLOCATE abc
Run Code Online (Sandbox Code Playgroud)

为了完整起见,UpdateAllStatistics过程.这将通过执行完整数据扫描来更新数据库中的所有统计信息:

RefreshAllStatistics.prc

CREATE PROCEDURE dbo.RefreshAllStatistics AS

EXECUTE sp_msForEachTable 'UPDATE STATISTICS ? WITH FULLSCAN'
Run Code Online (Sandbox Code Playgroud)

小智 7

您也可以"就地"执行此操作 - 无需获取所有create语句.

除了设置NOEXEC ON,您还需要设置您喜欢的SHOWPLAN_* ON(我使用SHOWPLAN_TEXT).现在,您可以摆脱步骤2,只执行在步骤1中检索到的每个过程.

以下是使用单个存储过程的示例.你可以把它放到你最喜欢的循环中:

create procedure tests @bob int as 
select * from missing_table_or_view
go 

set showplan_text on; 
go 

set noexec on 

exec tests 

set noexec off 
go 
set showplan_XML off 
go 
drop procedure tests 
go
Run Code Online (Sandbox Code Playgroud)

以上示例应生成以下输出:

消息208,级别16,状态1,过程测试,第2行
无效的对象名称'missing_table_or_view'.


And*_*eas 5

KenJ 建议的检查绝对是最好的检查,因为 recreate/alter-approaches 无法发现所有错误。例如

  • 由于查询提示而无法执行计划
  • 我什至有一个 SP 引用了一个不存在的表,但没有检测到错误。

请找到我的版本,它使用下面 KenJ 的方法一次检查所有现有的 SP。AFAIK,它会检测到每个阻止 SP 执行的错误。

--Forces the creation of execution-plans for all sps.
--To achieve this, a temporary SP is created that calls all existing SPs.
--It seems like the simulation of the parameters is not necessary. That makes things a lot easier.
DECLARE @stmt NVARCHAR(MAX) = 'CREATE PROCEDURE pTempCompileTest AS ' + CHAR(13) + CHAR(10)
SELECT @stmt = @stmt + 'EXEC [' + schemas.name + '].[' + procedures.name + '];'
    FROM sys.procedures
        INNER JOIN sys.schemas ON schemas.schema_id = procedures.schema_id
    WHERE schemas.name = 'dbo'
    ORDER BY procedures.name

EXEC sp_executesql @stmt
GO

--Here, the real magic happens.
--In order to display as many errors as possible, XACT_ABORT is turned off.
--Unfortunately, for some errors, the execution stops anyway.
SET XACT_ABORT OFF
GO
--Showplan disables the actual execution, but forces t-sql to create execution-plans for every statement.
--This is the core of the whole thing!
SET SHOWPLAN_ALL ON
GO
--You cannot use dynamic SQL in here, since sp_executesql will not be executed, but only show the string passed in in the execution-plan
EXEC pTempCompileTest
GO
SET SHOWPLAN_ALL OFF
GO
SET XACT_ABORT ON
GO
--drop temp sp again
DROP PROCEDURE pTempCompileTest
--If you have any errors in the messages-window now, you should fix these...
Run Code Online (Sandbox Code Playgroud)


Ale*_*ris 1

此外,您可能需要考虑使用Visual Studio Team System 2008 数据库版本,除其他外,它在构建时对项目中的所有存储过程进行静态验证,从而确保所有存储过程都与当前架构一致。