sp_MSforeachdb: only include results from databases with results

前端 未结 2 1163
南方客
南方客 2020-12-03 16:04

I\'m running the below stored procedure sp_MSforeachdb with a simple command. My question is how to limit the result to show only the databases that have at lea

相关标签:
2条回答
  • 2020-12-03 16:31

    You basically need another IF to only run the select if data exists. Here's what i did to test.

    On DB1:

    create table mytesttable(a int)
    insert mytesttable values(1)
    

    On DB2:

    create table mytesttable(a int)
    

    So you want DB1 to return results, but DB2 not to. you can use the following sql:

    EXECUTE master.sys.sp_MSforeachdb 'USE [?]; 
    
    IF (EXISTS (SELECT * 
                 FROM INFORMATION_SCHEMA.TABLES 
                 WHERE TABLE_NAME = ''mytesttable''))
    BEGIN
    
    IF EXISTS (SELECT 1 FROM mytesttable) BEGIN
        SELECT ''?'' as dbname,T.A
        FROM mytesttable AS T
    END
    END
    '
    

    This only returns: db1, 1

    0 讨论(0)
  • 2020-12-03 16:35

    Well, first, stop using sp_MSforEachDb. Oh, the problems (if you want proof, see here).

    How about:

    DECLARE @cmd NVARCHAR(MAX) = N'', @sql NVARCHAR(MAX) = N'';
    
    SELECT @cmd += N'IF EXISTS (SELECT 1 FROM '
      + QUOTENAME(name) + '.sys.tables WHERE name = N''Tabs'')
      SET @sql += N''UNION ALL 
        SELECT ''''' + name + ''''',T.TabName
        FROM ' + QUOTENAME(name) + '.dbo.Tabs AS T
        WHERE EXISTS 
        (
          SELECT 1 FROM ' + QUOTENAME(name) + '.dbo.TabModules AS TM
            WHERE TM.TabID = T.TabID
            AND TM.mID IN -- this should probably be exists too
            ( 
              ...
            )
        )
    '''
    FROM sys.databases 
      WHERE state = 0 -- assume you only want online databases
      AND database_id > 4; -- assume you don't want system dbs
    
    EXEC sp_executesql @cmd, N'@sql NVARCHAR(MAX) OUTPUT', @sql OUTPUT;
    
    SET @sql = STUFF(@sql, 1, 10, '') + N' ORDER BY TabName;';   
    
    PRINT @sql; -- this will appear truncated, but trust me, it is not truncated
    -- EXEC sp_executesql @sql;
    

    If you really want some unknown, arbitrary number of separate resultsets, the change is simple.

    DECLARE @cmd NVARCHAR(MAX) = N'', @sql NVARCHAR(MAX) = N'';
    
    SELECT @cmd += N'IF EXISTS (SELECT 1 FROM '
      + QUOTENAME(name) + '.sys.tables WHERE name = N''Tabs'')
      SET @sql += N''SELECT ''''' + name + ''''',T.TabName
        FROM ' + QUOTENAME(name) + '.dbo.Tabs AS T
        WHERE EXISTS 
        (
          SELECT 1 FROM ' + QUOTENAME(name) + '.dbo.TabModules AS TM
            WHERE TM.TabID = T.TabID
            AND TM.mID IN -- this should probably be exists too
            ( 
              ...
            )
        )
     ORDER BY T.TabName;
     '';'
    FROM sys.databases 
      WHERE state = 0 -- assume you only want online databases
      --AND database_id > 4; -- assume you don't want system dbs
    
    EXEC sp_executesql @cmd, N'@sql NVARCHAR(MAX) OUTPUT', @sql OUTPUT;
    
    PRINT @sql; -- this will appear truncated, but trust me, it is not truncated
    -- EXEC sp_executesql @sql;
    
    0 讨论(0)
提交回复
热议问题