我正在尝试建立一个过程,该过程将检查可用性组中所有服务器上的代理作业,并报告辅助副本中可能缺少的所有作业。
我对所有AG中的服务器进行了CMS设置,并且可以跨副本对代理作业运行查询,但是我只想返回某些服务器上的作业,但不是所有服务器上的作业。
我编写了一个查询来使用COUNT()获取此信息,但是由于查询结果是按服务器分组的,因此无法正常工作。我还尝试将结果放在临时表中以查看是否有帮助,但这似乎并没有太大的区别。
AG中有四台服务器,以下查询应返回不在所有四台服务器上的所有作业的名称,但是由于它似乎也返回了服务器名称,因此无法将它们识别为同一作业
CREATE TABLE #jobs (
JobName NVARCHAR(128))
INSERT INTO #jobs
SELECT name JobName
FROM sysjobs
SELECT *
FROM #jobs
GROUP BY JobName
HAVING COUNT(*) < 4
ORDER BY JobName
DROP TABLE #jobs
目前的查询会抛出如下结果集:
+------------+------------------------------------------+
| ServerName | JobName |
+------------+------------------------------------------+
| ServerA | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerA | OutputFile Cleanup |
| ServerB | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerB | IndexOptimize - USER_DATABASES |
| ServerC | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerB | IndexOptimize - USER_DATABASES |
| ServerD | DBA DatabaseBackup - AG_DATABASES - FULL |
| ServerD | Output File Cleanup |
+------------+------------------------------------------+
所有四个服务器都存在作业DBA DatabaseBackup-AG_DATABASES-FULL,因此我不希望返回该服务器,但是由于来自CMS连接的隐式servername列无法将它们识别为相同的值。
答案 0 :(得分:3)
正如GMB所述,您需要提取“名称”字段的一部分。
我建议将字符串分成ServerName和JobName。
假设名称以-分隔,例如在您的示例中,您的代码应如下所示。
CREATE TABLE #jobs (
ServerName NVARCHAR(128)
,JobName NVARCHAR(128))
INSERT INTO #jobs
SELECT
LEFT(name,CHARINDEX('-',name)-1) AS ServerName --Takes the Part left of the first -
, RIGHT(name,LEN(name) - CHARINDEX('-',name)) AS JobName --Takes the Part right of the first -
FROM sysjobs
SELECT JobName
FROM #jobs
GROUP BY JobName
HAVING COUNT(*) < 4
ORDER BY JobName
DROP TABLE #jobs
答案 1 :(得分:0)
因此,需要一个查询来返回条目少于4个的所有JobName
。创建临时表没有意义,只需直接查询sysjobs
表即可,例如:
SELECT name
FROM sysjobs
GROUP BY name
HAVING COUNT(*) < 4
ORDER BY name
答案 2 :(得分:0)
如果您的CMS始终插入服务器名称,然后插入作业名称,并用短划线将其括起来,并用空格括起来,那么您可以使用以下内容解析服务器名称:
INSERT INTO #jobs
SELECT REPLACE(SUBSTRING(name, CHARINDEX(' - ', name),LEN(name)) , ' - ', '') JobName
FROM sysjobs
答案 3 :(得分:0)
您可以使用STUFF()函数将所有服务器名称放在一列中,而仅计算作业名称。
SELECT JobName, STUFF((
SELECT ',' + CAST([ServerName] AS VARCHAR(MAX))
FROM sysjobs
WHERE results.JobNames = sysjobs.JobNames
FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
,1,1,'') AS ServerNames
FROM #jobs results
GROUP BY JobName
HAVING COUNT(*) < 4
ORDER BY JobName
答案 4 :(得分:0)
我设法以另一种方式解决它。现在,我在CMS服务器上设置了一个表,并且有一个存储过程,该过程将用AG中所有服务器上的代理作业的详细信息填充该表。 然后,我可以从那里运行以下查询,它就像一个超级按钮一样工作:
SELECT ServerName
,JobName
FROM AgentJobs
WHERE JobName IN(
SELECT JobName
FROM AgentJobs
WHERE JobCategory = 'Production'
GROUP BY JobName
HAVING COUNT(*) < 4)