0

我需要搜索具有特定前缀的某些数据库。找到这些数据库后,我需要检查某个模式是否存在以及是否不存在 - 使数据库脱机。我一直在尝试在 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'
4

3 回答 3

6

这是一种不依赖于未记录、不受支持和有缺陷的系统过程sp_msforeachdb的方法,也不依赖于类似的不可靠INFORMATION_SCHEMA视图

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' ... ';

错误:

消息 102,级别 15,状态 1,第 1 行
“...”附近的语法不正确。

你需要这样做:

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

但是,当您将命令嵌套在要发送到未记录、不受支持和有缺陷的系统过程的命令中时,这会很快变得令人费解。我知道我在这里重复自己。sp_msforeachdb我希望很明显,如果您想要可靠的结果,您不应该使用。

于 2013-04-23T23:34:59.020 回答
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
于 2013-04-24T06:25:07.730 回答
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匹配other BEGIN,尽管您可以完全删除 BEGIN-END 。
于 2013-04-24T00:58:44.200 回答