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

Single result for each database and group results by database

大家好,我是 SQL 的业余爱好者,但我花了几个小时寻找如何做到这一点,据我所知,没有人描述过它(至少没有说到点子上)我能理解)。

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

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

由于此查询只有 returns 个结果,我想按数据库名称对这些结果进行分组。如果它能让事情变得更简单,我只是 真正 对 "ArchivedDate" 感兴趣。

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

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)

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

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%'

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

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 的临时文件Table,其中包含存档日期字段(因为这是您所说的您最感兴趣的内容)。然后在循环中声明一个@CurrentDatabase 变量来保存当前数据库的值。然后它声明一个用于动态 SQL 语句的 @SQL 变量。然后声明用于循环过程的@Counter 变量。

下一行开始循环过程。一旦进入循环,@CurrentDatabase 将通过 selecting 来自 table 变量 @MyDatabases 的下一个顺序数据库来设置。然后使用@CurrentDatabase 变量设置动态SQL 语句。然后执行 Dynamic SQL Statement,将 Dynamic SQL String 的结果插入到 Temp Table.

最后,计数器递增。一旦跳出循环,所有结果都是从 Temp Table 中 select 编辑的。最后,温度 Table 被删除。

希望对您有所帮助。