18

すべてのストアド プロシージャが依然として構文的に有効であることを確認したいと考えています。(これは、誰かがテーブル/列の名前を変更/削除した場合に発生する可能性があります)。

現在、すべてのストアド プロシージャの構文をチェックする私の解決策は、Enterprise Manager に移動し、リストの最初のストアド プロシージャを選択して、次の手順を使用することです。

  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

すべての人の利益のために、すべてのストアド プロシージャを再コンパイルが必要であるとマークするストアド プロシージャ (ストアド プロシージャを再コンパイルするようにマークしても、構文的に有効かどうかはわかりません):

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

完全を期すために、UpdateAllStatisticsプロシージャを使用します。これにより、完全なデータ スキャンを実行して、データベース内のすべての統計が更新されます。

RefreshAllStatistics.prc

CREATE PROCEDURE dbo.RefreshAllStatistics AS

EXECUTE sp_msForEachTable 'UPDATE STATISTICS ? WITH FULLSCAN'
4

9 に答える 9

7

すべての作成ステートメントを取得せずに、これを「インプレース」で行うこともできます。

の設定に加えて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_text off; 
go 
drop procedure tests 
go

上記のサンプルは、次の出力を生成する必要があります。

メッセージ 208、レベル 16、状態 1、手順テスト、行 2
無効なオブジェクト名 'missing_table_or_view'。

于 2010-01-15T22:16:47.960 に答える
4

再作成/変更アプローチではすべてのエラーが検出されるわけではないため、KenJ によって提案されたチェックが間違いなく最適です。例えば

  • クエリヒントによる不可能な実行計画
  • エラーが検出されずに通過した存在しないテーブルを参照するSPさえありました。

以下の KenJ の方法で、既存のすべての SP を一度にチェックする私のバージョンを見つけてください。私の知る限り、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...
于 2015-09-15T06:55:31.063 に答える
3

SQL 2008 r2 以下を使用している場合は、使用しないでください。

NOEXEC をオンに設定

構文のみをチェックし、テーブルや列の存在などの潜在的なエラーはチェックしません。代わりに次を使用します。

FMTONLY をオンに設定

ストアド プロシージャのメタ データを返そうとすると、完全なコンパイルが実行されます。

2012 の場合、ストアド プロシージャを使用する必要があります: sp_describe_first_result_set

また、Tsql ですべての sp とビューをチェックする完全なスクリプトを実行することもできますが、これはほんの少しの作業です。

更新私は、すべてのユーザー定義のストアド プロシージャを通過し、そこに構文をチェックする tsql の完全なソリューションを作成しました。スクリプトは長くなりましたが、ここで見つけることができますhttp://chocosmith.wordpress.com/2012/12/07/tsql-recompile-all-views-and-stored-procedures-and-check-for-error/

于 2012-12-07T10:52:44.650 に答える
1

これがかなり古いことは知っていますが、実際にはすべてのストアド プロシージャを再作成するわずかに異なるバージョンを作成したため、コンパイルできない場合はエラーがスローされます。これは、SP_Recompile コマンドを使用しても実現できません。

CREATE PROCEDURE dbo.UTL_ForceSPRecompilation
(
    @Verbose BIT = 0
)
AS
BEGIN

    --Forces all stored procedures to recompile, thereby checking syntax validity.

    DECLARE @SQL NVARCHAR(MAX)
    DECLARE @SPName NVARCHAR(255)           

    DECLARE abc CURSOR FOR
         SELECT NAME, OBJECT_DEFINITION(o.[object_id])
         FROM sys.objects AS o 
         WHERE o.[type] = 'P'
         ORDER BY o.[name]

    OPEN abc

    FETCH NEXT FROM abc
    INTO @SPName, @SQL
    WHILE @@FETCH_STATUS = 0 
    BEGIN       

        --This changes "CREATE PROCEDURE" to "ALTER PROCEDURE"
        SET @SQL = 'ALTER ' + RIGHT(@SQL, LEN(@SQL) - (CHARINDEX('CREATE', @SQL) + 6))

        IF @Verbose <> 0 PRINT @SPName

        EXEC(@SQL)

        FETCH NEXT FROM abc
        INTO @SPName, @SQL
    END
    CLOSE abc
    DEALLOCATE abc  

END
于 2010-10-20T09:23:36.333 に答える
1

さらに、Visual Studio Team System 2008 Database Editionの使用を検討することもできます。これは、とりわけ、ビルド時にプロジェクト内のすべてのストアド プロシージャの静的検証を行い、すべてが現在のスキーマと一致していることを確認します。

于 2009-07-24T13:34:30.157 に答える
0

T-SQLやEnterpriseManagerからそれを行う方法はないので、クライアントコードから何かを書かなければなりませんでした。ここにすべてのコードを投稿するわけではありませんが、秘訣は次のとおりです。

1)すべてのストアドプロシージャのリストを取得します

 SELECT ROUTINE_NAME AS StoredProcedureName
 FROM INFORMATION_SCHEMA.ROUTINES
 WHERE ROUTINE_TYPE = 'PROCEDURE' --as opposed to a function
 ORDER BY ROUTINE_NAME

2)ストアドプロシージャを取得してT-SQLを作成します。

select
   c.text
from dbo.syscomments c
where c.id = object_id(N'StoredProcedureName')
order by c.number, c.colid
option(robust plan)

3)NOEXECをオンにしてcreateステートメントを実行し、構文がチェックされるようにしますが、実際にはストアドプロシージャを作成しようとはしません。

connection("SET NOEXEC ON", ExecuteNoRecords);
connection(StoredProcedureCreateSQL, ExecuteNoRecords);
connection("SET NOEXEC ON", ExecuteNoRecords);
于 2010-01-15T21:57:54.943 に答える
0

少し引き出されたオプション:

  1. データベースのコピーを作成します (バックアップと復元)。信頼度が高い場合は、ターゲット データベースでこれを行うことができます。
  2. SSMS を使用して、すべてのストアド プロシージャを 1 つのスクリプト ファイルにスクリプト化します。
  3. すべての手順を削除
  4. スクリプトを実行してそれらを再作成します。作成できないものはエラーになります。

ここには、次のような厄介な落とし穴がいくつかあります。

  • 「procが存在する場合は、proc GO create proc ... GO」構文を使用して、各プロシージャを分離する必要があります。
  • ネストされたプロシージャは、(再) 作成されていないプロシージャを呼び出すと失敗します。スクリプトを数回実行すると、それがキャッチされるはずです (適切に順序付けするのは非常に面倒な場合があるため)。
  • 他のもっとあいまいな問題が発生する可能性があるので、用心してください。

10 個または 1000 個のプロシージャをすばやく削除するには、次を実行します。

SELECT 'DROP PROCEDURE ' + schema_name(schema_id) + '.' +  name
 from sys.procedures

出力を選択して実行します。

これは、非常にまれなタスクを実行していることを前提としています。これを定期的に (毎日、毎週...) 行う必要がある場合は、その理由をお知らせください。

于 2009-07-24T14:05:07.730 に答える