How can I omit system databases and allow SQL Server 2008 agent job to move past ERROR_NUMBER 208?

孤街醉人 提交于 2019-12-13 03:56:07

问题


I have created a SQL Server 2008 Agent job that runs against all databases on the server. I am using the undocumented MS procedure, sp_MSforEachDB. I am specifying only certain databases to be processed and when these databases are found, if ERROR_NUMBER = 208, I want a table to be created and processing to continue to the next database. I also want to omit the system databases so the tabel doesn't get created in a system database. I though by specifying the names of the databases I want to process, I could create a table where none existed. The code I show below works if the 'focus' is set on a particular database. Also, when I run it, I get a table created in the master database, which I do not want to do. What I am trying to do with the code I created is: 1. select all the databases on the SQL server with name like "xyz_%" 2. if table "SESSIONS" exists, then delete all records older than 5 minutes 3. if table "SESSIONS" doesn't exist, then create it and continue processing - this is where I get the 208 error - invalid object because this table does not exist When the job sees there is no Sessions table, the job stops and no other databases are processed. I need all the named databases in 1 to be processed. If the SESSIONS table is not present, I get a 208 error that says "Invalid object name 'master.SchemaName.sessions'. If I set the 'focus' to the database without the sessions table, my code runs and the tables is created but I still get an error 208 - Invalid object name 'master.SchemaName.sessions'. No other error are displayed.

If someone could look at my code to see where my problem is, that would be great.

I have verified that I am getting the 208 error by using the Try Catch below. I also get error 2760 on the 2nd Try Catch that says the specified schema doesn't exist or I don't have access. I am an admin on this server.

I have been using SQL for a few years and I don't consider myself an expert. I have researched this on Google to come up with the code I have below. Any help would be appreciated.

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

回答1:


You could try using DB_ID(), I believe the DB_ID() is always 1-4 (unless you have a distribution database). In theory, just check to see if DB_ID() is greater than 4:

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

Also it doesn't look like you're using the correct database in the error handler - surely your try catch that creates the table should be in the call to sp_MSforeachdb as well?

I mean in your text you're running for each db, including this in a try catch:

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

One more thing - at the moment you seem to have hard coded the value reviewadmin.sessions in your permission granting code - I assume you meant that to be your new [?].[Schema].[Sessions] table - again which should be in the call to sp_MSforeachdb so it knows which database to run on.

I hope I've given you enough to go on, I'm not at a machine where I can write & test the whole thing I'm afraid!


If you just want databases with the name 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'

Note we can now skip the check for DB_ID > 4, since none of the system databases match your naming convention anyway.


OK, I've rethought this. Rather than trying and then catching the error if it fails, how about this new plan:

  1. Check if the database matches the naming convention you want.
  2. Check if the table exists.
  3. Create the table if it doesn't, grant permissions as before.
  4. Do the insert.

This should hopefully do it:

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'


来源:https://stackoverflow.com/questions/14320886/how-can-i-omit-system-databases-and-allow-sql-server-2008-agent-job-to-move-past

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!