【问题标题】:nvarchar limits to 8000 characters within stored procedurenvarchar 在存储过程中限制为 8000 个字符
【发布时间】:2016-09-28 09:24:05
【问题描述】:

我的存储过程有问题:

  ALTER PROCEDURE [dbo].[Sp_Calculate_TimeSheet_Global_Info]
        @DateDebut date,
        @DateFin date,
        @UserId int,
        @CA varchar(10)    
    AS


    BEGIN

       DECLARE @TaskQuery nvarchar(MAX) ;
       DECLARE @OPENQUERY nvarchar(MAX),@TSQL nvarchar(MAX), @LinkedServer nvarchar(MAX);
      DECLARE @DateDebut1 date;
      DECLARE @DateFin1 date;
      DECLARE @UserId1 int; 
      DECLARE @Query nvarchar(MAX);

       DECLARE @cond1 nvarchar(MAX);
       DECLARE @cond2 nvarchar(MAX);
       DECLARE @cond3 nvarchar(MAX);
       DECLARE @cond4 nvarchar(MAX);
       DECLARE @cond5 nvarchar(MAX);
       DECLARE @cond6 nvarchar(MAX);
       DECLARE @cond7 nvarchar(MAX);
       DECLARE @cond8 nvarchar(MAX);
       DECLARE @cond9 nvarchar(MAX);
       DECLARE @cond10 nvarchar(MAX);
       DECLARE @cond11 nvarchar(MAX);
       DECLARE @cond12 nvarchar(MAX);
       DECLARE @cond13 nvarchar(MAX);

       DECLARE @op nvarchar(MAX);
       DECLARE @where nvarchar(MAX);
       DECLARE @exec nvarchar(MAX);

       SET NOCOUNT ON;

     SET @LinkedServer = 'TASK'
     SET @OPENQUERY = 'SELECT * FROM OPENQUERY('+ @LinkedServer + ','''
     SET @DateDebut1 = @DateDebut;
     SET @DateFin1 = @DateFin;
     SET @UserId1 = @UserId;

     set @op = ' UNION ';
     set @where = ' where 1=1 ';

     set @cond1 = ' LEFT OUTER JOIN tickets tkt ON tkt.ttick_id = h.ttick_id  ';
     set @cond2 = ' RIGHT OUTER JOIN tickets tkt ON tkt.ttick_id = h.ttick_id  ';
     set @cond3 = ' LEFT OUTER JOIN ptasks tsk ON h.ptask_id = tsk.ptask_id  ';
     set @cond4 = ' RIGHT OUTER JOIN tasks tsk ON h.ptask_id = tsk.ptask_id  ';
     set @cond5 = ' LEFT OUTER JOIN phases ph ON tsk.phase_id = ph.phase_id  ';
     set @cond6 = ' RIGHT OUTER JOIN tasks tsk ON h.ptask_id = tsk.ptask_id  ';
     set @cond7 = ' LEFT OUTER JOIN projects p ON ph.proj_id = p.proj_id  ';
     set @cond8 = ' RIGHT OUTER JOIN projects p ON ph.proj_id = p.proj_id  ';
     set @cond9 = ' and h.hours_spent >= str_to_date(''''' + convert(varchar,@DateDebut,103) + ''''', ''''%d/%m/%Y'''')';
     set @cond10 = ' and h.hours_spent <= str_to_date(''''' + convert(varchar,@DateFin,103) + ''''', ''''%d/%m/%Y'''')';
     set @cond11 = ' and h.user_id=' + cast(@UserId as varchar);
     set @cond12 = ' and 
                       ( ph.phase_name like ''''' + '%' + @CA +'%' +''''' and (p.proj_name not like ''''' + '%' + @CA +'%' +''''' or p.proj_name is null) ) or
                       ( (ph.phase_name not like ''''' + '%' + @CA +'%' +''''' or ph.phase_name is null) and (p.proj_name not like ''''' + '%' + @CA +'%' +''''' or p.proj_name is null) and tsk.ptask_name like ''''' + '%' + @CA +'%' +''''') or
                       ( (ph.phase_name not like ''''' + '%' + @CA +'%' +''''' or ph.phase_name is null) and (p.proj_name not like ''''' + '%' + @CA +'%' +''''' or p.proj_name is null) and (tsk.ptask_name not like ''''' + '%' + @CA +'%' +''''' or tsk.ptask_name is null) and tkt.ttick_name like ''''' + '%' + @CA +'%' +''''') or
                       ( (p.proj_name not like ''''' + '%' + @CA +'%' +''''' or p.proj_name is null) and tsk.ptask_name like ''''' + '%' + @CA +'%' +''''' and (tsk.phase_id is null or tsk.phase_id =-1) ) or
                       ( (p.proj_name not like ''''' + '%' + @CA +'%' +''''' or p.proj_name is null) and tkt.ttick_name like ''''' + '%' + @CA +'%' +''''')
                        ';
     set @cond13 = ''') src';




      SET @TaskQuery  =N' SELECT  h.hours_id , h.hours_spent as  TimeSheet_Date, h.hours_hours as Hour_Number,h.hours_note as Hour_Note,(case when h.ttick_id is null or h.ttick_id=-1 then tsk.ptask_name else tkt.ttick_name end) as Task_Ticket_Libelle,(case when h.ttick_id is null or h.ttick_id=-1 then h.ptask_id else h.ttick_id end) as Task_Ticket_Id,h.proj_id as Project_Id,(case when h.ttick_id is null or h.ttick_id=-1 then 1 else 0 end) as Is_Task,h.user_id as User_Id,p.proj_name as Project_Name, u.user_uname as User_Name from users u RIGHT OUTER JOIN user_hours h  on u.user_id=h.user_id ' ;



      SET  @Query = @TaskQuery  ;

      SET @TaskQuery = @Query+   @cond1  ;

      SET @TaskQuery = @TaskQuery + @op +  @Query + @cond2    ;


      SET  @Query =  @TaskQuery  ;
      SET @TaskQuery = @Query + @cond3   ;
      SET @TaskQuery =@TaskQuery + @op +  @Query + @cond4    ;


      SET  @Query = @TaskLandQuery ;
      SET @TaskQuery = @Query + @cond5   ;
      SET @TaskQuery =@TaskQuery + @op +  @Query + @cond6    ;



      SET  @Query = @TaskQuery ;
      SET @TaskQuery = @Query + @cond7   ;
      SET @TaskQuery =@TaskQuery + @op +  @Query + @cond8    ;

      SET @TaskQuery = @TaskQuery + @where   ;



    IF(@DateDebut is not null)
    BEGIN 
       SET @TaskQuery = @TaskQuery + @cond9 ;
    END

    IF(@DateFin is not null)
    BEGIN 
       SET @TaskQuery =@TaskQuery + @cond10   ;
    END


    IF(@UserId is not null)
    BEGIN 
       SET @TaskQuery =  @TaskQuery +  @cond11   ;
    END

    IF(@CA is not null)
    BEGIN 
       SET @TaskQuery =  @TaskQuery + @cond12   ; 
    END

    set @TaskQuery = @TaskQuery + @cond13    ; 


      set @exec = @OPENQUERY+@TaskQuery;




    delete  from [dbo].[Timesheet_Global_Info]; 

    insert into [dbo].[Timesheet_Global_Info](
                [hours_id]
               ,[TimeSheet_Date]
               ,[Hour_Number]
               ,[Hour_Note]
               ,[Task_Ticket_Libelle]
               ,[Task_Ticket_Id]
               ,[Project_Id]
               ,[Is_Task]
               ,[User_Id]
               ,[Project_Name]
               ,[User_Name] 
               )

         EXEC (@exec) ; 

END

当我执行这个过程时,我得到这个错误:

消息 103,级别 15,状态 1,行 3 SELECT h.hours_id开头的字符串,h.hours_spent有TimeSheet_Date,h.hours_hours有Hour_Number,h.hours_note有Hour_Note,(CASE WHEN h.ttick'太长,最大长度8000。

异常是由于这一行EXEC (@exec) ;

所以我需要知道

  1. 这个错误的原因是什么?
  2. 我该如何解决?

【问题讨论】:

标签: sql sql-server tsql stored-procedures


【解决方案1】:

您使用的是OPENQUERY,根据 MSDN,查询的最大大小为 8KB,即 8000 个字符,超出了您的查询范围。

OPENQUERY ( linked_server ,'query' )  

'query'是在链接服务器中执行的查询字符串。这 字符串的最大长度为 8 KB。

【讨论】:

  • @mhasen 那么我该如何解决这个问题
【解决方案2】:

为什么不使用sp_executesql

EXEC sp_executesql @exec

我可以看到@execnvarchar(max),你可以毫无问题地通过它。

在 64 位服务器上,字符串的大小限制为 2 GB,即 nvarchar(max) 的最大大小。

编辑

使用sp_executesql 代替OPENQUERY

DECLARE @paramDef nvarchar(max) = '@TaskQuery nvarchar(max)'

SELECT @exec = 'INSERT INTO [dbo].[Timesheet_Global_Info] EXEC '+QUOTENAME(@LinkedServer)+'.database.dbo.sp_executesql @TaskQuery',

EXEC sp_executesql @exec, @paramDef, @TaskQuery=@TaskQuery

【讨论】:

  • 问题出在OpenQuery函数而不是变量@exec的大小
  • 我明白了!您正在尝试从链接服务器的 OPENQUERY 执行一些选择,并将此数据插入某处?我做对了吗?您可以使用EXEC remoteserver.database.dbo.sp_executesql 'dynamic SQL'; 执行不带OPENQUERY 的查询。这将用 8000 个字符串解决您的问题。
  • 我在回答中添加了一些信息,希望对您有所帮助。
【解决方案3】:

超过最大长度字符,在这种情况下,您必须将动态查询拆分为多个部分并通过组合执行。

Declare @Query1 VARCHAR(MAX),@Query2 VARCHAR(MAX)

SET @Query1='SELECT * FROM'
SET @Query2=' Employee'

EXEC (@Query1+@Query2)

你的情况可能是

EXEC (@OPENQUERY+@TaskQuery);

如果您仍然遇到相同的错误,请将您的变量拆分为更多...

【讨论】:

  • 正如@mhasen 提到的,即使EXEC (@OPENQUERY+@TaskQuery); 对我也不起作用
  • 就像我说的那样,他必须分得更多
  • OpenQuery 的唯一签名是OPENQUERY ( linked_server ,'query' ),所以不能拆分第二个参数
  • 我认为你必须拆分@TaskQuery
猜你喜欢
  • 2023-03-14
  • 2014-07-25
  • 2015-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多