0

サーバー上のすべてのデータベースに対して実行される SQL Server 2008 エージェント ジョブを作成しました。文書化されていない MS 手順を使用していますsp_MSforEachDB。処理する特定のデータベースのみを指定しており、これらのデータベースが見つかった場合、ERROR_NUMBER = 208、テーブルを作成して次のデータベースに処理を進めたい。また、テーブルがシステム データベースに作成されないように、システム データベースを省略したいと考えています。処理したいデータベースの名前を指定することで、何も存在しないテーブルを作成できました。以下に示すコードは、「フォーカス」が特定のデータベースに設定されている場合に機能します。また、実行すると、マスター データベースにテーブルが作成されますが、これは望ましくありません。私が作成したコードでやろうとしていることは次のとおりです。 1.「xyz_%」のような名前の SQL サーバー上のすべてのデータベースを選択します 2.テーブル「SESSIONS」が存在する場合は、5 分より古いすべてのレコードを削除します 3.ifテーブル「SESSIONS」が存在しない場合は、それを作成して処理を続行します-これが私が取得する場所です208 error - invalid object because this table does not exist ジョブが Sessions テーブルがないことを確認すると、ジョブは停止し、他のデータベースは処理されません。すべての名前付きデータベースを 1 で処理する必要があります。SESSIONS テーブルが存在しない場合、「無効なオブジェクト名 'master.SchemaName.sessions'」という 208 エラーが発生します。セッション テーブルのないデータベースに「フォーカス」を設定すると、コードが実行され、テーブルが作成されますしかし、それでもエラー 208 - Invalid object name 'master.SchemaName.sessions' が表示されます。他のエラーは表示されません。

誰かが私のコードを見て、私の問題がどこにあるかを確認できれば、それは素晴らしいことです。

以下の Try Catch を使用して、208 エラーが発生していることを確認しました。また、2 回目の Try Catch で、指定されたスキーマが存在しないか、アクセス権がないことを示すエラー 2760 が表示されます。私はこのサーバーの管理者です。

私は数年間 SQL を使用してきましたが、自分自身を専門家とは考えていません。Google でこれを調査して、以下のコードを作成しました。どんな助けでも大歓迎です。

declare @ERROR INT

BEGIN TRY

exec sp_MSforeachdb 'IF "[?]" NOT IN ("master", "model","msdb", "tempdb")
BEGIN
 DELETE FROM [?].schema.sessions WHERE name like ''xyz_%''
 AND sessionStart <DATEADD(mi, -5,GETDATE())
END'                  

END TRY

BEGIN CATCH
SELECT  ERROR_NUMBER() AS error_number,  ERROR_MESSAGE() AS error_message
    SELECT @ERROR = ERROR_NUMBER()
    If @ERROR = 208
    BEGIN TRY
     /* create the Sessions table */
     BEGIN
     CREATE TABLE  [SCHEMA].[SESSIONS](
       [authuser] [varchar](30) NULL,
       [sessionID] [char](36) NULL,
       [sessionStart] [datetime] NULL)

grant select,delete on reviewadmin.sessions to public;
     END
    END TRY  
 BEGIN CATCH 
  SELECT  ERROR_NUMBER() AS error_number,  ERROR_MESSAGE() AS error_message
 END CATCH 
 END CATCH
4

1 に答える 1

1

を使用してみてください。 は常に 1 ~ 4DB_ID()であると思います (ディストリビューション データベースDB_ID()を使用している場合を除く)。理論的には、DB_ID() が 4 より大きいかどうかを確認するだけです。

exec sp_MSforeachdb 'IF DB_ID(''?'')) > 4
BEGIN
 DELETE FROM [?].schema.sessions WHERE name like ''xyz_%''
 AND sessionStart <DATEADD(mi, -5,GETDATE())
END' 

また、エラー ハンドラで正しいデータベースを使用しているようには見えません。テーブルを作成する try catch も呼び出しにsp_MSforeachdb含まれているはずです。

あなたのテキストでは、これをtry catchに含めて、各データベースに対して実行しています:

CREATE TABLE [?].[SCHEMA].[SESSIONS]
(
   [authuser]     [VARCHAR](30) NULL,
   [sessionID]    [CHAR](36) NULL,
   [sessionStart] [DATETIME] NULL
)

reviewadmin.sessionsもう1つ-現時点では、アクセス許可コードで値をハードコーディングしているようです-それが新しい[?].[Schema].[Sessions]テーブルであることを意味していると思います-これも呼び出しに含まれている必要があるsp_MSforeachdbため、実行するデータベースを認識します。

先に進むのに十分な情報を提供できたことを願っています。残念ながら、すべてを記述してテストできるマシンではありません。


名前のデータベースだけが必要な場合xyz_%

exec sp_MSforeachdb 'IF DB_NAME() LIKE ''xyz_%''
BEGIN
 DELETE FROM [?].schema.sessions WHERE name like ''xyz_%''
 AND sessionStart <DATEADD(mi, -5,GETDATE())
END'

DB_ID > 4 のチェックをスキップできることに注意してください。どのシステム データベースも命名規則に一致しないためです。


わかりました、私はこれを再考しました。試行して失敗した場合にエラーをキャッチするのではなく、次の新しい計画はどうですか。

  1. データベースが必要な命名規則と一致しているかどうかを確認してください。
  2. テーブルが存在するかどうかを確認します。
  3. そうでない場合はテーブルを作成し、以前と同様に権限を付与します。
  4. 挿入を行います。

これでうまくいくはずです:

EXEC Sp_msforeachdb 'IF ''?'' LIKE ''xyz_%''
                    BEGIN
                        IF OBJECT_ID(''?.REVIEWADMIN.Sessions'', ''U'') IS NULL
                        BEGIN
                            CREATE TABLE [?].ReviewAdmin.Sessions
                            (
                                [authuser]     [VARCHAR](30) NULL,
                                [sessionID]    [CHAR](36) NULL,
                                [sessionStart] [DATETIME] NULL
                            )

                            grant select,delete on reviewadmin.sessions to public;

                        END

                        DELETE FROM [?].ReviewAdmin.Sessions
                        WHERE sessionStart < DATEADD(mi, -5,GETDATE())

                    END'
于 2013-01-14T16:01:43.830 に答える