【问题标题】:How can I omit system databases and allow SQL Server 2008 agent job to move past ERROR_NUMBER 208?如何省略系统数据库并允许 SQL Server 2008 代理作业超过 ERROR_NUMBER 208?
【发布时间】:2013-01-16 00:58:20
【问题描述】:

我创建了一个针对服务器上所有数据库运行的 SQL Server 2008 代理作业。我正在使用未记录的 MS 程序 sp_MSforEachDB。我只指定要处理的某些数据库,当找到这些数据库时,如果ERROR_NUMBER = 208,我希望创建一个表并继续处理到下一个数据库。我还想省略系统数据库,这样表格就不会在系统数据库中创建。虽然通过指定我要处理的数据库的名称,我可以创建一个不存在的表。如果在特定数据库上设置了“焦点”,我在下面显示的代码有效。此外,当我运行它时,我在主数据库中创建了一个表,我不想这样做。我试图用我创建的代码做的是: 1.选择SQL服务器上所有名称如“xyz_%”的数据库 2.如果表“SESSIONS”存在,则删除所有超过5分钟的记录 3. 如果表“SESSIONS”不存在,则创建它并继续处理 - 这是我得到208 error - invalid object because this table does not exist的地方 当作业发现没有 Sessions 表时,作业停止并且不处理其他数据库。我需要处理 1 中的所有命名数据库。如果 SESSIONS 表不存在,我会收到一个 208 错误,提示“无效的对象名称'master.SchemaName.sessions'。如果我将'焦点'设置为没有会话表的数据库,我的代码将运行并创建表但我仍然收到错误 208 - Invalid object name 'master.SchemaName.sessions'。没有显示其他错误。

如果有人可以查看我的代码以了解我的问题出在哪里,那就太好了。

我已使用下面的 Try Catch 验证我收到了 208 错误。我还在第二次尝试 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

【问题讨论】:

    标签: sql-server sql-server-2008 sp-msforeachdb


    【解决方案1】:

    您可以尝试使用DB_ID(),我相信DB_ID() 始终是1-4(除非您有distribution database)。理论上只要看看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-我假设您的意思是成为您的新[?].[Schema].[Sessions] 表-再次应该在对@ 的调用中987654329@ 所以它知道要在哪个数据库上运行。

    我希望我已经给了你足够的继续,我不在一台可以编写和测试整个东西的机器上,我害怕!


    如果您只想要名称为 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'
    

    【讨论】:

    • 感谢您的回复。我添加了代码 'IF DB_ID(''?'') > 4 ,这似乎已经从处理中删除了系统数据库。有没有办法让这个代码只适用于名称为 xyz_% 的所有数据库?我只需要处理名称为 xyz_% 的数据库。您建议的代码适用于系统数据库 - 还有其他数据库存在,我不想包括在内,并按名称指定它们,如 xyz_% 是我想做的。我想先解决这个问题,然后再解决其他问题。
    • 对于架构 - 我将使用 reviewadmin.sessions 所以 reviewadmin 可以代替上面的 [schema}。
    • 我添加了您的代码,现在我收到错误 207 - 列“名称”无效。我尝试了 DB_NAME,除了 DB_NAME 作为无效列之外,我得到了同样的错误。
    • @user1927354 奇怪,为我工作。尝试将''?'' 放入第一行,如下所示:IF DB_NAME(''?'') LIKE ''xyz_%''
    • 如果我使用 'IF DB_NAME like "xyz_%" ',我还需要 where name like "xyz_%" 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多