每个数据库和组的单个结果按数据库结果

时间:2015-03-18 16:57:18

标签: sql sql-server tsql

嘿伙计们,我是SQL的业余爱好者,但我花了几个小时寻找如何做到这一点,据我所知,没有人描述过(至少没有达到我能理解的程度)。

我需要针对服务器上的每个45(非系统)数据库运行SQL查询:

SELECT TOP 1 IdTransaction, IdDateTime, ArchivedDate, RetentionCategoryIdentity
FROM Saveset
WHERE NOT EXISTS (
    SELECT * FROM HoldSaveset 
    WHERE saveset.SavesetIdentity = HoldSaveset.SavesetIdentity)

由于此查询仅返回一个结果,因此我想按数据库名称对这些结果进行分组。如果它让事情变得更容易,我只是真的对“ArchivedDate”感兴趣。

2 个答案:

答案 0 :(得分:1)

您可以使用动态SQL创建select语句。只需将您想要的表名放在@targetTable变量中。它将创建一个存储结果的表。希望这可以帮助!如果您有任何疑问,请告诉我们!

DECLARE @sql VARCHAR(MAX),
        @targetTable VARCHAR(100);

SELECT @sql = 'select top 1 IdTransaction, IdDateTime, ArchivedDate, RetentionCategoryIdentity ' + 
        'FROM '+ QUOTENAME(name) + '.dbo.Saveset AS A '
        + 'where NOT exists (Select * from ' + QUOTENAME(name) + '.dbo.HoldSaveset AS B ' + 'WHERE A.SavesetIdentity = B.SavesetIdentity) UNION ALL ' + COALESCE(@sql,'')
FROM master..sysdatabases
WHERE NAME NOT IN('master','tempdb','model','msdb')


SET @targetTable = 'database.schema.tablename'
SELECT @sql = 'SELECT * INTO ' + @targetTable + ' FROM (' + SUBSTRING(@sql,0,LEN(@SQL) -8) + ') A';

EXEC (@sql)

答案 1 :(得分:1)

您可以使用NAME字段上的某种过滤器查询sys.databases,以将所需的所有数据库名称插入表变量中。包括可用于循环的顺序字段。代码看起来像这样。

DECLARE @MyDatabases TABLE (DbName VARCHAR(500), RowNum INT IDENTITY(1,1))
INSERT INTO @MyDatabases (DbName)
SELECT name
  FROM sys.databases
 WHERE name LIKE '%filter names here%'

一旦您想要的数据库位于表变量中,您就可以遍历表,在表变量中为每个数据库执行一次动态SQL语句,并将结果插入到临时表中。循环完成后,您可以从临时表中选择所有值以获得最终结果。执行此操作的代码如下所示。

CREATE TABLE #MyData (ArchivedDate VARCHAR(100), DbName VARCHAR(500))
DECLARE @CurrentDatabase VARCHAR(500)
DECLARE @SQL VARCHAR(MAX)
DECLARE @Counter INT = 1

WHILE @Counter <= (SELECT MAX(RowNum) FROM @MyDatabases)
BEGIN
   SELECT @CurrentDatabase = DbName
     FROM @MyDatabases 
    WHERE RowNum = @Counter

   SET @SQL = 'INSERT INTO #MyData(ArchivedDate, DbName)
               SELECT TOP 1 ArchivedDate, ''' + @CurrentDatabase + '''
                 FROM ' + @CurrentDatabase + '.dbo.Saveset a
                WHERE NOT EXISTS (SELECT * FROM ' + @CurrentDatabase + '.dbo.HoldSaveset b WHERE a.SavesetIdentity = b.SavesetIdentity)'
   EXEC(@SQL)

   SET @Counter = @Counter + 1

END

SELECT * FROM #MyData
DROP TABLE #MyData

代码说明:此代码首先创建一个名为#MyData的临时表,其中包含“存档日期”字段(因为您说的是您最感兴趣的内容)。然后声明一个@CurrentDatabase变量来保存循环中当前数据库的值。然后它声明用于动态SQL语句的@SQL变量。然后声明用于循环过程的@Counter变量。

下一行开始循环过程。进入循环后,通过从表变量@MyDatabases中选择下一个顺序数据库来设置@CurrentDatabase。然后使用@CurrentDatabase变量设置动态SQL语句。然后执行动态SQL语句,将动态SQL字符串的结果插入临时表。

最后,计数器递增。一旦退出循环,所有结果都从Temp Table中选择。最后,临时表被删除了。

希望有所帮助。