1

サーバー上のすべてのデータベースを反復処理し、いくつかの異なるデータベースからのデータの集計をテーブル変数に入力するストアドプロシージャを作成しています。関係がないので興味のないデータベースもあります。問題は、CURSORが気にしないデータベースを反復処理すると、存在しないテーブルに対してSELECTステートメントが発行されることです。Invalid object name例外を無視して処理を続行するにはどうすればよいですか?

編集

無関係なデータベースをスキップしようとした方法は次のとおりです。

DECLARE db_cursor CURSOR FOR

SELECT name
FROM MASTER.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb') 

OPEN db_cursor 

FETCH NEXT FROM db_cursor INTO @currentDatabaseName  

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sql = 'SELECT COUNT(Name) FROM ' + @currentDatabaseName + '.sys.Tables WHERE Name = ''SomeTableICareAbout'''

        INSERT INTO @tableSearchResult
        EXEC sp_executesql @sql

        SET @tableCount = (SELECT COUNT(*) FROM @tableSearchResult WHERE TableCount = 1)

        --If the table I care about was found, then do the good stuff
        IF @tableCount > 0
            ...

このアプローチの問題は、実行中のユーザー(私の場合はサービスアカウント)がテーブルのSELECTにアクセスできない場合、そのエラーについてはわかりません。ユーザーがSELECTアクセス権を持っていない場合は、その例外を発生させたいと思います。ただし、ユーザーがSELECTアクセス権を持っていない場合でも、sys.TablesビューでSELECTを実行できます。

4

2 に答える 2

4

エラー208は、コンパイル時およびコードが実際に実行される前に発生する名前解決エラーであるため、直接キャッチすることはできません。動作は文書化されています。説明については、「TRY…CATCHコンストラクトの影響を受けないエラー」というセクションを参照してください。この質問への回答には、いくつかの興味深いコメントがあります。

ドキュメントの「ソリューション」に加えて、動的SQLを使用できます。この例では、エラーがキャッチされます。

begin try
    exec('select * from dbo.ThisTableDoesNotExist');
end try
begin catch
    select error_number();
end catch;

すべてのデータベースをループしている場合は、とにかくどこかで動的SQLを使用している可能性が高いため、これがケースに適している可能性があります。

于 2012-10-10T20:54:38.893 に答える
1

ストアドプロシージャ内でエラーを実行している場合は、エラーをキャッチできます(ここに記載されている例:http://msdn.microsoft.com/en-us/library/ms175976.aspx

また、動的SQLを変更して次のようなことを行うこともできます

SET @sql = '
        If Exists(Select Name From  ' + @currentDatabaseName + '.sys.Tables 
            WHERE Name = ''SomeTableICareAbout'')' --+
        --Add Whatever the Good Stuff is
EXEC sp_executesql @sql

ただし、テーブルからselect count(1)を実行する代わりに、テーブルが最初に存在するかどうかを確認すると、そのエラーが発生するのを防ぐことができます。

于 2012-10-11T14:02:04.970 に答える