对多个服务器的 SQL 查询失败

Posted

技术标签:

【中文标题】对多个服务器的 SQL 查询失败【英文标题】:SQL query to multiple servers fails 【发布时间】:2019-09-29 21:16:08 【问题描述】:

我尝试使用 SSMS 对多个已注册的 SQL Server 运行此查询:

SELECT DISTINCT(volume_mount_point), 
    total_bytes / 1048576 AS Size_in_MB, 
    available_bytes / 1048576 AS Free_in_MB,
    (SELECT ROUND(CAST(available_bytes / 1048576 * 1.0 as FLOAT) / CAST(total_bytes / 1048576 * 1.0 AS FLOAT) * 100, 2)) AS FreePercentage
FROM 
    sys.master_files AS f 
CROSS APPLY 
    sys.dm_os_volume_stats(f.database_id, f.file_id)
GROUP BY
    volume_mount_point, total_bytes / 1048576, available_bytes / 1048576  
ORDER BY 
    4

某些服务器具有不知道“sys.dm_os_volume_stats”和整个查询崩溃报告的 SQL Server 2008 R2 RTM 产品级别:

消息 208,第 16 级,状态 1,第 1 行 无效的对象名称“sys.dm_os_volume_stats”。

我尝试在主 SELECT 之前添加一个条件,但它不起作用:

  DECLARE @ProductLevel varchar(128)  
  SET @ProductLevel = CONVERT(VARCHAR(128), SERVERPROPERTY ('ProductLevel'))
  IF @ProductLevel not like 'RTM'
    BEGIN...

我还尝试通过此文档来区分结果 To change the multiserver results options

更改多服务器结果选项 在 Management Studio 中,在 工具菜单,点击选项。

展开查询结果,展开 SQL Server,然后单击多服务器 结果。

在“多服务器结果”页面上,指定您设置的选项设置 想要,然后点击确定。

还有其他想法吗?

【问题讨论】:

【参考方案1】:

如果 DMV 不存在,则不会评估 IF 条件,因为整个批处理在编译时失败,因此永远不会执行 IF 语句。

一种解决方法是将查询包装在条件动态 SQL 中:

IF CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS varchar(20)),4) AS int) > 10 OR 
    (CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS varchar(20)),4) AS int) = 10
     AND CAST(PARSENAME(CAST(SERVERPROPERTY('ProductVersion') AS varchar(20)),3) AS int) = 5
     AND SERVERPROPERTY('ProductLevel') <> 'RTM')
BEGIN
EXEC sp_executesql N'
SELECT DISTINCT(volume_mount_point), 
    total_bytes / 1048576 AS Size_in_MB, 
    available_bytes / 1048576 AS Free_in_MB,
    (SELECT ROUND(CAST(available_bytes / 1048576 * 1.0 as FLOAT) / CAST(total_bytes / 1048576 * 1.0 AS FLOAT) * 100, 2)) AS FreePercentage
FROM 
    sys.master_files AS f 
CROSS APPLY 
    sys.dm_os_volume_stats(f.database_id, f.file_id)
GROUP BY
    volume_mount_point, total_bytes / 1048576, available_bytes / 1048576  
ORDER BY 
    4;
'
END;

【讨论】:

我刚刚尝试对两台测试服务器(均非 RTM)运行您的查询,它只返回:“server1\DB1(登录):(4 行受影响)” @JosefB.,忘记包括产品级别检查,所以我添加了它。 现在我明白你的目标了!我只需要稍微调整一下您的查询。 SQL2008 R2 RTM的Product版本为10.50.1600.1,SQL2008 R2 SP2的Product版本为10.50.4042.0,其中集成了sys.dm_os_volume_stats。因此,在我的环境中,许多 SQL 服务器无法满足条件“ProductVersion >= 11”,但无论如何您的查询会对我有很大帮助。当我得到完整的工作查询时,我会回来的。谢谢! @JosefB.,抱歉,我没有方便测试的 SQL 2008 R2 RTM 实例。我用我认为可行的条件调整了查询​​。 首先 - 请不要道歉 - 我很高兴你能帮助我。第二件事,我将条件简化为“IF (EXISTS (SELECT * FROM sys.all_objects WHERE name = 'dm_os_volume_stats'))”。第三件事 - 不必将其作为 存储过程 执行,但我仍然必须将 Tools\Multiserver results\Merge results 的参数设置为 False

以上是关于对多个服务器的 SQL 查询失败的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to SQL查询基于使用外键与使用内置导航属性成功或失败

Azure Synapse 无服务器 SQL 池 - 查询执行失败

通过powershell Enter-PSSession连接到SQL Server 2012(使用Windows身份验证)

对 SQL 文件的所有 MS Access 查询

phpMyAdmin 不允许我一次运行多个查询,并且导入我的 SQL 失败

Oracle数据库多个实例的查询与指定