如何在sp_MSforeachdb中指定TABLE_SCHEMA名称以使数据库脱机

时间:2013-04-23 23:23:12

标签: sql-server sp-msforeachdb

我需要搜索具有特定前缀的某些数据库。找到这些数据库后,我需要检查某个模式是否存在以及是否存在 - 使数据库脱机。我一直在尝试在Google上找到的各种建议,但没有任何效果。我有一个错误,我无法通过。错误是' XYZ'不是公认的选择。如果我将代码分开运行正常,但是当我添加sp_MSforeachdb时,错误会返回。

EXEC sp_msforeachdb 'IF ''?'' LIKE ''abc_%''
  BEGIN
      IF (NOT EXISTS  (SELECT *
               FROM INFORMATION_SCHEMA.TABLES 
               WHERE TABLE_SCHEMA = 'XYZ'          
                               BEGIN
                               ALTER DATABASE [abc_xxxxxxxxx] SET OFFLINE WITH
                               ROLLBACK IMMEDIATE             
                               END'  

此代码可以正常工作:

SELECT *
 FROM INFORMATION_SCHEMA.TABLES 
 WHERE TABLE_SCHEMA = 'XYZ'

3 个答案:

答案 0 :(得分:6)

这是一种不依赖undocumented, unsupported and buggy system procedure sp_msforeachdb的方法,也不依赖于similarly unreliable INFORMATION_SCHEMA views

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'IF NOT EXISTS (SELECT 1 FROM ' 
  + QUOTENAME(name) + '.sys.tables AS t
  INNER JOIN ' + QUOTENAME(name) + '.sys.schemas AS s
  ON t.schema_id = s.schema_id
  WHERE s.name = ''XYZ'')
  BEGIN
    EXEC sp_executesql N''ALTER DATABASE ' 
      + QUOTENAME(name) + ' SET OFFLINE;''
  END
' FROM sys.databases WHERE name LIKE 'abc_%';

PRINT @sql;
-- EXEC sp_executesql @sql;

您的实际错误是因为字符串中包含字符串分隔符。你不能这样做:

SELECT ' WHERE TABLE_SCHEMA = 'XYZ' ... ';

错误:

  

Msg 102,Level 15,State 1,Line 1
  “...”附近的语法不正确。

你需要这样做:

SELECT ' WHERE TABLE_SCHEMA = ''XYZ'' ... ';

然而,当您在命令中嵌入命令时,这会很快变得错综复杂,而这些命令是您发送给未记录的,不受支持且错误的系统过程的。我知道我在这里重复自己。我希望很明显,如果你想要可靠的结果,你不应该使用sp_msforeachdb

答案 1 :(得分:1)

试试这个 -

DECLARE 
      @schema_name SYSNAME
    , @database_name SYSNAME

SELECT 
      @schema_name = 'XYZ'
    --, @database_name = 'abc_%'

DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = (SELECT '
USE [' + d.name + '];
IF NOT EXISTS (
    SELECT 1 
    FROM sys.objects o
    JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
    WHERE o.type = ''U'' 
        AND s.name = ''' + @schema_name + '''
) EXEC sp_executesql N''ALTER DATABASE [' + d.name + '] SET OFFLINE;''
' 
FROM sys.databases d 
WHERE (@database_name IS NULL OR d.name LIKE @database_name)
    AND d.[state] = 0
    AND d.name NOT IN ('master', 'tempdb', 'model', 'msdb')
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')

EXEC sp_executesql @sql

答案 2 :(得分:0)

你有一些小错误

EXEC sp_msforeachdb '
IF ''?'' LIKE ''abc_%''
  BEGIN
      IF NOT EXISTS ( SELECT *
                      FROM INFORMATION_SCHEMA.TABLES 
                      WHERE TABLE_SCHEMA = ''XYZ'')
          ALTER DATABASE [abc_xxxxxxxxx] SET OFFLINE WITH ROLLBACK IMMEDIATE             
  END'
  1. 您已绕过''?''''abc_%''周围的引号,但忘记了'XYZ'
  2. 括号不匹配 - 您有两个左括号但没有近括号
  3. ALTER DATABASE语句是一行,不需要BEGIN-END。删除BEGIN允许END其他 BEGIN匹配,但您可以完全删除BEGIN-END。