sp_MSforeachdb:仅包含具有结果的数据库的结果

时间:2013-11-21 21:10:29

标签: sql sql-server-2008 stored-procedures

我使用简单的命令运行以下存储过程sp_MSforeachdb。我的问题是如何限制结果只显示至少有1条记录满足命令的数据库:

Sample of the result

这是我的存储过程:

EXECUTE master.sys.sp_MSforeachdb 'USE [?]; 

IF (EXISTS (SELECT * 
                 FROM INFORMATION_SCHEMA.TABLES 
                 WHERE TABLE_NAME = ''Tabs''))
BEGIN

SELECT ''?'' as dbname,T.TabName, T.TabPath
FROM Tabs T
WHERE T.TabID IN (

SELECT Distinct TM.TabID
FROM TabModules TM
WHERE mID IN (
  ...
  )

)
ORDER BY T.TabName
END
'

任何想法如何修改sp以便它不显示具有空结果的数据库(见图)?

2 个答案:

答案 0 :(得分:11)

首先,请停止使用sp_MSforEachDb。哦,问题(如果你需要证据,请参阅hereherehere)。

怎么样:

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;

如果您真的想要一些未知的,任意数量的单独结果集,那么更改很简单。

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;

答案 1 :(得分:1)

如果数据存在,你基本上只需要另一个IF来运行select。 这就是我要做的测试。

在DB1上:

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

在DB2上:

create table mytesttable(a int)

所以你希望DB1返回结果,但DB2不要。你可以使用以下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
'

这只会返回: db1,1