Sql server 在没有链接服务器的单独服务器上运行特殊SQL代码
我正在尝试使用SQL Server中的存储过程构建一个监控解决方案(存储过程的结果通过电子邮件发送) 我们有大约100台不同的服务器,由于安全原因,未配置链接服务器 我使用SSMS中央管理服务器将存储过程部署到每台服务器。(如果在所有系统上都启用了DB mail,我会将这些SP的输出直接发送给DBA,但邮件仅在CMS服务器上启用。) 当未启用链接服务器时,如何获取这些存储过程的输出 我曾尝试通过链接的服务器运行存储过程,但我遇到了Kerebos错误-我们的系统被锁定太久,而且在进行更改时存在太多的官僚作风 下面是我的逻辑伪代码。我现在面临的主要问题与代码的这一部分有关:Sql server 在没有链接服务器的单独服务器上运行特殊SQL代码,sql-server,sql-server-2012,Sql Server,Sql Server 2012,我正在尝试使用SQL Server中的存储过程构建一个监控解决方案(存储过程的结果通过电子邮件发送) 我们有大约100台不同的服务器,由于安全原因,未配置链接服务器 我使用SSMS中央管理服务器将存储过程部署到每台服务器。(如果在所有系统上都启用了DB mail,我会将这些SP的输出直接发送给DBA,但邮件仅在CMS服务器上启用。) 当未启用链接服务器时,如何获取这些存储过程的输出 我曾尝试通过链接的服务器运行存储过程,但我遇到了Kerebos错误-我们的系统被锁定太久,而且在进行更改时存在太多
SELECT *
FROM OPENROWSET('SQLNCLI', 'Server=BBMAG552;Trusted_Connection=yes;',
'EXEC master.dbo.usp_sizing '''database''') AS a;
完整代码如下:
-- Pseduocode
--Build list of all servers registered in CMS
SELECT DISTINCT groups.name AS 'Server Group Name'
,svr.server_name AS 'Server Name'
FROM msdb.dbo.sysmanagement_shared_server_groups_internal groups
INNER JOIN msdb.dbo.sysmanagement_shared_registered_servers_internal svr
ON groups.server_group_id = svr.server_group_id;
GO
-- execute the stored procedure against list of all servers using a
-- sp_MSforeachdb
SELECT *
FROM OPENROWSET('SQLNCLI', 'Server=BBMAG552;Trusted_Connection=yes;',
'EXEC master.dbo.usp_sizing '''database''') AS a;
-- This script is run on all our servers.
CREATE PROCEDURE dbo.usp_Sizing @Granularity VARCHAR(10) = NULL, @Database_Name sysname = NULL AS
DECLARE @SQL VARCHAR(5000)
IF EXISTS (SELECT NAME FROM tempdb..sysobjects WHERE NAME = '##Results')
BEGIN
DROP TABLE ##Results
END
CREATE TABLE ##Results ([Database Name] sysname,
[File Name] sysname,
[Physical Name] NVARCHAR(260),
[File Type] VARCHAR(4),
[Total Size in Mb] INT,
[Available Space in Mb] INT,
[Growth Units] VARCHAR(15),
[Max File Size in Mb] INT)
SELECT @SQL =
'USE [?] INSERT INTO ##Results([Database Name], [File Name], [Physical Name],
[File Type], [Total Size in Mb], [Available Space in Mb],
[Growth Units], [Max File Size in Mb])
SELECT DB_NAME(),
[name] AS [File Name],
physical_name AS [Physical Name],
[File Type] =
CASE type
WHEN 0 THEN ''Data'''
+
'WHEN 1 THEN ''Log'''
+
'END,
[Total Size in Mb] =
CASE ceiling([size]/128)
WHEN 0 THEN 1
ELSE ceiling([size]/128)
END,
[Available Space in Mb] =
CASE ceiling([size]/128)
WHEN 0 THEN (1 - CAST(FILEPROPERTY([name], ''SpaceUsed''' + ') as int) /128)
ELSE (([size]/128) - CAST(FILEPROPERTY([name], ''SpaceUsed''' + ') as int) /128)
END,
[Growth Units] =
CASE [is_percent_growth]
WHEN 1 THEN CAST(growth AS varchar(20)) + ''%'''
+
'ELSE CAST(growth*8/1024 AS varchar(20)) + ''Mb'''
+
'END,
[Max File Size in Mb] =
CASE [max_size]
WHEN -1 THEN NULL
WHEN 268435456 THEN NULL
ELSE [max_size]
END
FROM sys.database_files
ORDER BY [File Type], [file_id]'
--Print the command to be issued against all databases
PRINT @SQL
--Run the command against each database
EXEC sp_MSforeachdb @SQL
--UPDATE ##Results SET [Free Space %] = [Available Space in Mb]/[Total Size in Mb] * 100
--Return the Results
--If @Database_Name is NULL:
IF @Database_Name IS NULL
BEGIN
IF @Granularity = 'Database'
BEGIN
SELECT
T.[Database Name],
T.[Total Size in Mb] AS [DB Size (Mb)],
T.[Available Space in Mb] AS [DB Free (Mb)],
T.[Consumed Space in Mb] AS [DB Used (Mb)],
D.[Total Size in Mb] AS [Data Size (Mb)],
D.[Available Space in Mb] AS [Data Free (Mb)],
D.[Consumed Space in Mb] AS [Data Used (Mb)],
CEILING(CAST(D.[Available Space in Mb] AS decimal(10,1))/D.[Total Size in Mb]*100) AS [Data Free %],
L.[Total Size in Mb] AS [Log Size (Mb)],
L.[Available Space in Mb] AS [Log Free (Mb)],
L.[Consumed Space in Mb] AS [Log Used (Mb)],
CEILING(CAST(L.[Available Space in Mb] AS decimal(10,1))/L.[Total Size in Mb]*100) AS [Log Free %]
FROM
(
SELECT [Database Name],
SUM([Total Size in Mb]) AS [Total Size in Mb],
SUM([Available Space in Mb]) AS [Available Space in Mb],
SUM([Total Size in Mb]-[Available Space in Mb]) AS [Consumed Space in Mb]
FROM ##Results
GROUP BY [Database Name]
) AS T
INNER JOIN
(
SELECT [Database Name],
SUM([Total Size in Mb]) AS [Total Size in Mb],
SUM([Available Space in Mb]) AS [Available Space in Mb],
SUM([Total Size in Mb]-[Available Space in Mb]) AS [Consumed Space in Mb]
FROM ##Results
WHERE ##Results.[File Type] = 'Data'
GROUP BY [Database Name]
) AS D ON T.[Database Name] = D.[Database Name]
INNER JOIN
(
SELECT [Database Name],
SUM([Total Size in Mb]) AS [Total Size in Mb],
SUM([Available Space in Mb]) AS [Available Space in Mb],
SUM([Total Size in Mb]-[Available Space in Mb]) AS [Consumed Space in Mb]
FROM ##Results
WHERE ##Results.[File Type] = 'Log'
GROUP BY [Database Name]
) AS L ON T.[Database Name] = L.[Database Name]
ORDER BY CEILING(CAST(D.[Available Space in Mb] AS decimal(10,1))/D.[Total Size in Mb]*100)
END
ELSE
BEGIN
SELECT [Database Name],
[File Name],
[Physical Name],
[File Type],
[Total Size in Mb] AS [DB Size (Mb)],
[Available Space in Mb] AS [DB Free (Mb)],
CEILING(CAST([Available Space in Mb] AS decimal(10,1)) / [Total Size in Mb]*100) AS [Free Space %],
[Growth Units],
[Max File Size in Mb] AS [Grow Max Size (Mb)]
FROM ##Results
END
END
--Return the Results
--If @Database_Name is provided
ELSE
BEGIN
IF @Granularity = 'Database'
BEGIN
SELECT
T.[Database Name],
T.[Total Size in Mb] AS [DB Size (Mb)],
T.[Available Space in Mb] AS [DB Free (Mb)],
T.[Consumed Space in Mb] AS [DB Used (Mb)],
D.[Total Size in Mb] AS [Data Size (Mb)],
D.[Available Space in Mb] AS [Data Free (Mb)],
D.[Consumed Space in Mb] AS [Data Used (Mb)],
CEILING(CAST(D.[Available Space in Mb] AS decimal(10,1))/D.[Total Size in Mb]*100) AS [Data Free %],
L.[Total Size in Mb] AS [Log Size (Mb)],
L.[Available Space in Mb] AS [Log Free (Mb)],
L.[Consumed Space in Mb] AS [Log Used (Mb)],
CEILING(CAST(L.[Available Space in Mb] AS decimal(10,1))/L.[Total Size in Mb]*100) AS [Log Free %]
FROM
(
SELECT [Database Name],
SUM([Total Size in Mb]) AS [Total Size in Mb],
SUM([Available Space in Mb]) AS [Available Space in Mb],
SUM([Total Size in Mb]-[Available Space in Mb]) AS [Consumed Space in Mb]
FROM ##Results
WHERE [Database Name] = @Database_Name
GROUP BY [Database Name]
) AS T
INNER JOIN
(
SELECT [Database Name],
SUM([Total Size in Mb]) AS [Total Size in Mb],
SUM([Available Space in Mb]) AS [Available Space in Mb],
SUM([Total Size in Mb]-[Available Space in Mb]) AS [Consumed Space in Mb]
FROM ##Results
WHERE ##Results.[File Type] = 'Data'
AND [Database Name] = @Database_Name
GROUP BY [Database Name]
) AS D ON T.[Database Name] = D.[Database Name]
INNER JOIN
(
SELECT [Database Name],
SUM([Total Size in Mb]) AS [Total Size in Mb],
SUM([Available Space in Mb]) AS [Available Space in Mb],
SUM([Total Size in Mb]-[Available Space in Mb]) AS [Consumed Space in Mb]
FROM ##Results
WHERE ##Results.[File Type] = 'Log'
AND [Database Name] = @Database_Name
GROUP BY [Database Name]
) AS L ON T.[Database Name] = L.[Database Name]
ORDER BY D.[Database Name]
END
ELSE
BEGIN
SELECT [Database Name],
[File Name],
[Physical Name],
[File Type],
[Total Size in Mb] AS [DB Size (Mb)],
[Available Space in Mb] AS [DB Free (Mb)],
CEILING(CAST([Available Space in Mb] AS decimal(10,1))/[Total Size in Mb]*100) AS [Free Space %],
[Growth Units],
[Max File Size in Mb] AS [Grow Max Size (Mb)]
FROM ##Results
WHERE [Database Name] = @Database_Name
END
END
DROP TABLE ##Results
假设您可以直接连接到所有这些实例,您可以尝试在本地运行某种C#实用程序,连接到服务器,运行存储过程,获取结果,然后将其显示给您。假设您可以直接连接到所有这些实例,您可以尝试某种在本地运行的C#实用程序,它连接到服务器,运行存储过程,获取结果,然后将结果显示给您。而Powershell可以做C#可以做的任何事情,而且不需要编译器。@DavidBrowne Microsoft我之所以推荐C#是因为我相信它能更优雅地处理异步操作,但我承认我的PowerShell fu没有它应有的好-我可能弄错了:)虽然PowerShell中没有异步/等待语言支持,但您可以直接使用任务API。谢谢您的建议。这当然是我将要研究的问题,但我怀疑我可能会面临问题,因为DMZ后面有许多服务器,而且通过客户端应用程序进行外部访问并不总是可能的。@Asher没问题!恕我直言,如果您无法直接连接,无法通过链接服务器连接,并且IT部门无法/不会帮助您,那么您可能有点运气不佳。不过,希望其他人会有更好的答案!Powershell可以做C所能做的任何事情,而且不需要编译器。@DavidBrowne Microsoft我推荐C的原因是因为我相信它处理异步操作更优雅,但我承认我的PowerShell fu没有它应有的好-我可能弄错了:)虽然PowerShell中没有异步/等待语言支持,但您可以直接使用任务API。谢谢您的建议。这当然是我将要研究的问题,但我怀疑我可能会面临问题,因为DMZ后面有许多服务器,而且通过客户端应用程序进行外部访问并不总是可能的。@Asher没问题!恕我直言,如果您无法直接连接,无法通过链接服务器连接,并且IT部门无法/不会帮助您,那么您可能有点运气不佳。不过,希望其他人会有更好的答案!