为什么SQL脚本可以在本地环境中运行但无法在其他服务器上运行

时间:2013-04-24 09:23:41

标签: sql sql-server

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

  

Msg 537,Level 16,State 3,Line 40
  传递给LEFT或SUBSTRING函数的长度参数无效。

我也尝试直接在远程服务器上运行“select”部分,结果也是正确的。 我不明白为什么会出错。有什么想法吗? (注意:我在错误行中添加“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

2 个答案:

答案 0 :(得分: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

也许如果你试图解释你想要实现什么,可能会发布一个更好的查询。

答案 1 :(得分: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]感到不安。如果它位于执行任务的同一服务器上,则可能拒绝使用该数据库。