복붙노트

[SQL] NVARCHAR (최대) 아직 잘리지

SQL

NVARCHAR (최대) 아직 잘리지

나는 MS SQL Server 2008의 저장 프로 시저를 쓰고 있어요 그래서 그것은 정말로 긴 쿼리 내가 @query라는 변수를 생성하고 유형 NVARCHAR (MAX)의 그것을 만들 그래서 나는 동적으로 작성해야합니다. 지금, 나는이 SQL 서버, NVARCHAR (MAX)의 현대 버전에서 원래 4000 문자 최대보다 더 많은 방법을 데이터의 말도 안되는 금액을 보유 할 수 있다고 들었습니다. 나는 그것을 밖으로 인쇄 할 때, @query는 여전히 4000 자로 잘립니다지고있다.

DECLARE @Query NVARCHAR(max);
SET @Query = 'SELECT...' -- some of the query gets set here
SET @Query = @Query + '...' -- more query gets added on, etc.

-- later on...
PRINT LEN(@Query) -- Prints out 4273, which is correct as far as I can tell
PRINT @Query      -- Truncates value to 4000 characters
EXEC sp_executesql @Query -- totally crashes due to malformed (truncated) query

오전 내가 잘못 일을하고, 아니면 NVARCHAR (MAX)가 어떻게 작동하는지에 대해 완전히 잘못입니까?

해결법

  1. ==============================

    1.생성 된 동적 SQL을 보려면 텍스트 모드로 변경 (바로 가기 : Ctrl 키-T), 다음 SELECT를 사용

    생성 된 동적 SQL을 보려면 텍스트 모드로 변경 (바로 가기 : Ctrl 키-T), 다음 SELECT를 사용

    PRINT LEN(@Query) -- Prints out 4273, which is correct as far as I can tell
    --SET NOCOUNT ON
    SELECT @Query
    

    sp_executesql에 관해서는,이 (텍스트 모드),이 세 가지 AAAAA를 표시해야합니다 시도 ... SELECT ... '추가'와 가장 긴되는 가운데 일이야 '를. 제 2 출력의 단부 (4510)을 도시 우측 하단에있는 상태 바의 LN ... .. 골 표시 시계.

    declare @n nvarchar(max)
    set @n = REPLICATE(convert(nvarchar(max), 'a'), 4500)
    SET @N = 'SELECT ''' + @n + ''''
    print @n   -- up to 4000
    select @n  -- up to max
    exec sp_Executesql @n
    
  2. ==============================

    2.문제는 SET 문으로 관련이있는 것으로 보인다. 나는 표현의 크기는 4,000 바이트되지 않을 수 있다고 생각합니다. 당신이하려고하는 모든 이상 4,000 자 동적으로 생성 된 문을 지정하는 경우 모든 설정을 변경할 필요가 없습니다. 당신이해야하는 과제를 분할하는 것입니다. 당신의 문은 6,000 자하는 경우, 동일한 변수에 대한 논리적 브레이크 포인트 다음 CONCATENATE 하반기을 찾을 수 있습니다. 예를 들면 :

    문제는 SET 문으로 관련이있는 것으로 보인다. 나는 표현의 크기는 4,000 바이트되지 않을 수 있다고 생각합니다. 당신이하려고하는 모든 이상 4,000 자 동적으로 생성 된 문을 지정하는 경우 모든 설정을 변경할 필요가 없습니다. 당신이해야하는 과제를 분할하는 것입니다. 당신의 문은 6,000 자하는 경우, 동일한 변수에 대한 논리적 브레이크 포인트 다음 CONCATENATE 하반기을 찾을 수 있습니다. 예를 들면 :

    SET @Query = 'SELECT ....' [Up To 4,000 characters, then rest of statement as below]
    
    SET @Query = @Query + [rest of statement]
    

    이제 정상으로 쿼리를 실행 즉 EXEC (@query)

  3. ==============================

    3.당신이 합치되는 유니 코드가있는 경우 / NCHAR / NVARCHAR는 값, 다음 SQL Server는 암시 적으로 NVARCHAR (4000)로 문자열을 변환 것이며, 당신의 문자열을 자르거나 심지어 당신에게 데이터가되었다는 경고를 줄 것이다 실현하기 위해 불행하게도 너무 바보 그 문제에 관해서 잘립니다! 긴 문자열 합치하는 경우 (또는 당신이 느끼는 문자열을 할 수있을 긴) 항상 (NVARCHAR (MAX로 '')) CAST과 같이 사용하여 문자열 건물을 사전에 연결할 :

    당신이 합치되는 유니 코드가있는 경우 / NCHAR / NVARCHAR는 값, 다음 SQL Server는 암시 적으로 NVARCHAR (4000)로 문자열을 변환 것이며, 당신의 문자열을 자르거나 심지어 당신에게 데이터가되었다는 경고를 줄 것이다 실현하기 위해 불행하게도 너무 바보 그 문제에 관해서 잘립니다! 긴 문자열 합치하는 경우 (또는 당신이 느끼는 문자열을 할 수있을 긴) 항상 (NVARCHAR (MAX로 '')) CAST과 같이 사용하여 문자열 건물을 사전에 연결할 :

    SET @Query = CAST('' as nVarChar(MAX))--Force implicit conversion to nVarChar(MAX)
               + 'SELECT...'-- some of the query gets set here
               + '...'-- more query gets added on, etc.
    

    어떤 고통과 무서운 것은이 SQL 서버가 작동 얼마나 생각합니다. :( 나는 / 여러 SET로 코드를 헤어 여러 변수를 사용하여 할당을 선택 말하는 웹에있는 다른 해결 방법을 알고 있지만,이 위의 솔루션을 제공 할 필요가 없습니다. 이 암시 적으로 VARCHAR (8000)로 변환 그래서 더 유니 코드 없었기 때문에 8000 문자 최대 히트 사람들을 위해, 아마이었다. 설명: 어떤 무대 뒤에서 일어나는 것은 당신이 사용 (MAX)에 할당하는 변수, SQL Server는 값의 오른쪽을 평가합니다 비록 당신이 NVARCHAR (4000) 또는 VARCHAR (8000) (따라 먼저 및 기본 할당하는 것입니다 )이 합치하는지에. 이 값을 알아내는 이루어집니다 (그리고 당신을 위해 그것을 절단 후) 그 다음으로 변환 한 후에 (MAX)하지만 너무 늦기하여, 당신의 변수에 할당 할 때.

  4. ==============================

    4.텍스트 결과는 8192 자까지 가능합니다.

    텍스트 결과는 8192 자까지 가능합니다.

    나는이 방법을 사용

    DECLARE @Query NVARCHAR(max);
    
    set @Query = REPLICATE('A',4000)
    set @Query = @Query + REPLICATE('B',4000)
    set @Query = @Query + REPLICATE('C',4000)
    set @Query = @Query + REPLICATE('D',4000)
    
    select LEN(@Query)
    
    SELECT @Query /*Won't contain any "D"s*/
    SELECT @Query as [processing-instruction(x)] FOR XML PATH /*Not truncated*/
    
  5. ==============================

    5.첫 번째 문제는 PRINT 문의 제한 사항입니다. 나는 sp_executesql에 실패하는 이유를 모르겠어요. 그것은 입력의 거의 모든 길이를 지원해야한다.

    첫 번째 문제는 PRINT 문의 제한 사항입니다. 나는 sp_executesql에 실패하는 이유를 모르겠어요. 그것은 입력의 거의 모든 길이를 지원해야한다.

    아마도 쿼리가 잘못되었습니다 이유는 절단 이외이다.

  6. ==============================

    6.4000 개 문자에 8000, NVARCHAR (MAX)로 자릅니다에게 VARCHAR (MAX)를 인쇄합니다.

    4000 개 문자에 8000, NVARCHAR (MAX)로 자릅니다에게 VARCHAR (MAX)를 인쇄합니다.

    그러나;

    PRINT CAST(@query AS NTEXT)
    

    전체 쿼리를 인쇄합니다.

  7. ==============================

    7.오늘 같은 문제가 발생하고 4000 자 제한을 넘어, 나는 두 개의 문자열로 동적 쿼리를 분할하고 쿼리를 실행할 때 그들을 연결하는 남겼습니다.

    오늘 같은 문제가 발생하고 4000 자 제한을 넘어, 나는 두 개의 문자열로 동적 쿼리를 분할하고 쿼리를 실행할 때 그들을 연결하는 남겼습니다.

    DECLARE @Query NVARCHAR(max);
    DECLARE @Query2 NVARCHAR(max);
    SET @Query = 'SELECT...' -- some of the query gets set here
    SET @Query2 = '...' -- more query gets added on, etc.
    
    EXEC (@Query + @Query2)
    
  8. ==============================

    8.출력 모든이 인쇄 BIG 기능을 사용 :

    출력 모든이 인쇄 BIG 기능을 사용 :

    IF OBJECT_ID('tempdb..#printBig') IS NOT NULL
      DROP PROCEDURE #printBig
    
    GO
    
    CREATE PROCEDURE #printBig (
       @text NVARCHAR(MAX)
     )
    AS
    
    --DECLARE @text NVARCHAR(MAX) = 'YourTextHere'
    DECLARE @lineSep NVARCHAR(2) = CHAR(13) + CHAR(10)  -- Windows \r\n
    
    DECLARE @off INT = 1
    DECLARE @maxLen INT = 4000
    DECLARE @len INT
    
    WHILE @off < LEN(@text)
    BEGIN
    
      SELECT @len =
        CASE
          WHEN LEN(@text) - @off - 1 <= @maxLen THEN LEN(@text)
          ELSE @maxLen
                 - CHARINDEX(REVERSE(@lineSep),  REVERSE(SUBSTRING(@text, @off, @maxLen)))
                 - LEN(@lineSep)
                 + 1
        END
      PRINT SUBSTRING(@text, @off, @len)
      --PRINT '@off=' + CAST(@off AS VARCHAR) + ' @len=' + CAST(@len AS VARCHAR)
      SET @off += @len + LEN(@lineSep)
    
    END
    

    출처:

    https://www.richardswinbank.net/doku.php?id=tsql:print_big

  9. ==============================

    9.문자열 표현식을 사용하여 동적 SQL을 만드는 문제는 SQL 4,000 문자로 문자열 식의 평가를 제한 않는다는 것입니다. 당신은 NVARCHAR (최대) 변수에 긴 문자열을 할당 할 수 있지만 당신이 표현에 + 포함 빨리으로 (예 : + CASE ... END의 +로), 다음 식의 결과는 4000 개 문자로 제한됩니다.

    문자열 표현식을 사용하여 동적 SQL을 만드는 문제는 SQL 4,000 문자로 문자열 식의 평가를 제한 않는다는 것입니다. 당신은 NVARCHAR (최대) 변수에 긴 문자열을 할당 할 수 있지만 당신이 표현에 + 포함 빨리으로 (예 : + CASE ... END의 +로), 다음 식의 결과는 4000 개 문자로 제한됩니다.

    이 문제를 해결하는 한 가지 방법은 + 대신 CONCAT를 사용하는 것입니다. 예를 들면 :

    SET @sql = CONCAT(@sql, N'
         ... dynamic SQL statements ...
        ', CASE ... END, N'
         ... dynamic SQL statements ...
        ')
    

    @Sql은 NVARCHAR (최대)로 선언되는 경우.

  10. from https://stackoverflow.com/questions/4833549/nvarcharmax-still-being-truncated by cc-by-sa and MIT license