0

我编写了一个 SQL 脚本来将名称映射到报告名称。我已经在我的本地 SQL Server 2012 机器上进行了验证。它运作良好。但是,当我在服务器中运行时,出现错误

消息 537,级别 16,状态 3,行 40
传递给 LEFT 或 SUBSTRING 函数的长度参数无效。

而且我还尝试直接在远程服务器中运行“选择”部分,结果也是正确的。我不明白为什么它是错误的。有什么想法吗?(注意:我在错误行中添加了“error here-->”)

DECLARE @jobTable TABLE 
(
  job_name nvarchar(max),
  report_name nvarchar(max),
  event_type nvarchar(max),
  description nvarchar(max),
  last_run_date int,
  last_run_time int
)

declare
  @job_name uniqueidentifier,
  @report_name nvarchar(max),
  @event_type nvarchar(max),
  @description nvarchar(max),
  @last_run_date int,
  @last_run_time int,
  @last_run_dur int



/************** alert ********/
declare getId_alertjob_cursor cursor for (
     SELECT 
       [jobs].[name] job_name,
       alertFeed.relativePath report_name,
         CONVERT(nvarchar(max), SUBSTRING([steps].[command], CHARINDEX(' @EventType=''', [steps].[command], 0) + LEN(' @EventType='''), CHARINDEX('''', [steps].[command], CHARINDEX(' @EventType=''', [steps].[command]) + LEN(' @EventType=''')) - CHARINDEX(' @EventType=''', [steps].[command], 0) - LEN(' @EventType=''')), 0) event_type,
       [steps].[last_run_date] last_date,
       [steps].[last_run_time] last_time,
       [steps].[last_run_duration] last_dur
       FROM [msdb].[dbo].[sysjobs] [jobs] INNER JOIN [msdb].[dbo].[sysjobsteps] [steps] ON [jobs].[job_id] = [steps].[job_id], ReportingService_4c0ed75e1e8c4e50acbf853867f071f3_Alerting.dbo.AlertDefinition [alertDef], ReportingService_4c0ed75e1e8c4e50acbf853867f071f3_Alerting.dbo.Feed [alertFeed]
       WITH (NOLOCK)
       WHERE [jobs].[name] <> 'syspolicy_purge_history' 
       and alertDef.scheduleid = CONVERT(nvarchar(max), SUBSTRING([steps].[command], CHARINDEX(' @EventData=''', [steps].[command], 0) + LEN(' @EventData='''), CHARINDEX('''', [steps].[command], CHARINDEX(' @EventData=''', [steps].[command]) + LEN(' @EventData=''')) - CHARINDEX(' @EventData=''', [steps].[command], 0) - LEN(' @EventData=''')), 0)
       and alertDef.FeedId = alertFeed.FeedId
);

open getId_alertjob_cursor 
error here-->    fetch next from getId_alertjob_cursor INTO   @job_name,   @report_name,  @event_type,  @last_run_date,  @last_run_time, @last_run_dur

while @@FETCH_STATUS = 0
BEGIN
--     INSERT INTO @jobTable VALUES (@job_name, @report_name, @event_type,'Alert',0,0);
--   ,@last_run_date,@last_run_time);
     fetch next from getId_alertjob_cursor INTO   @job_name,   @report_name,  @event_type,  @last_run_date,  @last_run_time,@last_run_dur
END

close getId_alertjob_cursor
deallocate getId_alertjob_cursor
4

2 回答 2

1

我怀疑这是因为有些作业的步骤不包含该短语@EventType=',这导致您的子字符串失败。

添加一个快速签入以确保它首先存在,如下所示:

Case 
        When CHARINDEX(' @EventType=''', [steps].[command]) > 0 Then
        CONVERT(nvarchar(max), SUBSTRING([steps].[command], CHARINDEX(' @EventType=''', [steps].[command], 0) + LEN(' @EventType='''), CHARINDEX('''', [steps].[command], CHARINDEX(' @EventType=''', [steps].[command]) + LEN(' @EventType=''')) - CHARINDEX(' @EventType=''', [steps].[command], 0) - LEN(' @EventType=''')), 0) 
        Else ''
        End as [EventType]

刚刚注意到你的 WHERE 子句中有这个:

and alertDef.scheduleid = CONVERT(nvarchar(max), SUBSTRING([steps].[command], CHARINDEX(' @EventData=''', [steps].[command], 0) + LEN(' @EventData='''), CHARINDEX('''', [steps].[command], CHARINDEX(' @EventData=''', [steps].[command]) + LEN(' @EventData=''')) - CHARINDEX(' @EventData=''', [steps].[command], 0) - LEN(' @EventData=''')), 0)

您还应该添加一个检查以查看该command字段是否包含@EventData

也许如果您尝试解释您要达到的目标,那么某人可能会发布更好的查询。

于 2013-04-24T09:35:07.880 回答
0

首先,我想提一下,在这种情况下不需要使用游标。即您的查询可以简化为以下内容:

DECLARE @jobTable TABLE 
(
      job_name SYSNAME
    , report_name SYSNAME
    , event_type NVARCHAR(1000)
    , [description] NVARCHAR(2000)
    , last_run_date INT
    , last_run_time INT
)

INSERT INTO @jobTable 
(
      job_name
    , report_name
    , event_type
    , last_run_date
    , last_run_time
)
SELECT 
      d.job_name
    , report_name = alertFeed.relativePath
    , d.event_type
    , d.last_date
    , d.last_time
FROM (
    SELECT 
          job_name = j.[name] 
        , event_type = CASE WHEN CHARINDEX(' @EventType=''', s.[command]) > 0 
            THEN CONVERT(NVARCHAR(MAX), SUBSTRING(s.[command], CHARINDEX(' @EventType=''', s.[command], 0) + LEN(' @EventType='''), CHARINDEX('''', s.[command], CHARINDEX(' @EventType=''', s.[command]) + LEN(' @EventType=''')) - CHARINDEX(' @EventType=''', s.[command], 0) - LEN(' @EventType=''')), 0) 
            ELSE ''
          END
        , last_date = s.[last_run_date] 
        , last_time = s.[last_run_time] 
    FROM [msdb].dbo.sysjobs j WITH (NOLOCK)
    JOIN [msdb].dbo.sysjobsteps s WITH (NOLOCK) ON j.job_id = s.job_id 
    WHERE j.[name] != 'syspolicy_purge_history' 
) d
JOIN [ReportingService_4c0ed75e1e8c4e50acbf853867f071f3_Alerting].dbo.AlertDefinition [alertDef] ON alertDef.scheduleid = event_type
JOIN [ReportingService_4c0ed75e1e8c4e50acbf853867f071f3_Alerting].dbo.Feed [alertFeed] ON alertDef.FeedId = alertFeed.FeedId

此外,我对数据库 [ReportingService_..._Alerting] 感到不安。如果它位于执行任务的同一台服务器上,则可能值得拒绝使用数据库。

于 2013-04-24T10:45:35.543 回答