programing

SQL NVARCHAR 및 VARCHAR 제한

goodsources 2023. 4. 21. 20:49
반응형

SQL NVARCHAR 및 VARCHAR 제한

모두, 대규모(회피할 수 없는) 동적 SQL 쿼리가 있습니다.선택 기준의 필드 수에 따라 동적 SQL을 포함하는 문자열이 4000자를 초과합니다.이것으로, 최대 4000 의 설정이 있는 것을 알 수 있습니다.NVARCHAR(MAX), Profiler의 스테이트먼트를 확인합니다.

DELARE @SQL NVARCHAR(MAX);
SET @SQL = 'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO

동작(?)하는 것 같습니다.또한 큰 쿼리는 이 4000 제한(?)과 관련된 오류를 발생시킵니다.기본적으로 이 4000 제한 후에 모든 SQL이 트리밍되고 구문 오류가 발생합니다.프로파일러에서는 이 경우에도 이 동적 SQL 쿼리는 풀(?)로 표시됩니다.

이 @SQL 변수를 VARCHAR로 변환하고 계속 진행하면 어떻게 될까요?

시간 내주셔서 감사합니다.

Ps. 이러한 큰 쿼리를 보기 위해 4000자 이상의 문자를 출력할 수 있으면 좋겠습니다.다음은 4000으로 제한됩니다.

SELECT CONVERT(XML, @SQL);
PRINT(@SQL);

다른 멋진 방법은 없을까?

으로 설정되어 을 알고 .NVARCHAR(MAX)

당신의 이해는 틀렸습니다. nvarchar(max)는 최대 2GB의 데이터(10억 더블바이트 문자)를 저장할 수 있습니다.

Books online의 nchar와 nvarchar에서 문법은 다음과 같습니다.

nvarchar [ ( n | max ) ]

|character는 이것들이 대안임을 의미합니다. 즉, 다음 중 하나를 지정합니다. n 문자 의 「」를 사용합니다.max.

의 「」를 .n에서 4,000 여야 합니다.단, 1의 4를 사용합니다.max는 큰 오브젝트 데이터형(는 권장되지 않는 치환)으로 정의합니다.

실제로 SQL Server 2008에서는 변수의 경우 2GB 제한을 무한정 초과할 수 있습니다.tempdb(여기에 표시)

질문의 다른 부분에 대해서

연결 시 잘라내는 방법은 데이터 유형에 따라 다릅니다.

  1. varchar(n) + varchar(n).
  2. nvarchar(n) + nvarchar(n)4000달러입니다.
  3. varchar(n) + nvarchar(n)4000달러입니다. nvarchar으로는 우선도가 됩니다.nvarchar(4,000)
  4. [n]varchar(max)+[n]varchar(max) 미만일 경우2GB는 잘리지 않습니다.
  5. varchar(max)+varchar(n)의 경우 (2GB의 경우)로 됩니다.varchar(max).
  6. varchar(max)+nvarchar(n)의 경우 (2GB의 경우)로 됩니다.nvarchar(max).
  7. nvarchar(max)+varchar(n)합니다.varchar(n)nvarchar(n)그 다음 연결을 합니다.문자열 길이가 4,000자를 초과할 경우 캐스팅이 완료되고 잘립니다.

문자열 리터럴의 데이터 유형

「 」를하고 있는 는,N및 4,입니다. prefix는 prefix로 됩니다.nvarchar(n)서 ''는n을 사용하다 ★★★★★★★★★★★★★★★★★.N'Foo' will will로 nvarchar(3) 4000자됩니다.nvarchar(max)

를 않는 N및이며 prefix는 prefix 8,000자로 됩니다.varchar(n)서 ''는n을 사용하다보다 긴 경우varchar(max)

의 두 모두 "0" 입니다.n11로 .

새로운 구문 요소

1. CONCAT는 여기서 되지 않는다

DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);

SELECT DATALENGTH(@A5000 + @A5000), 
       DATALENGTH(CONCAT(@A5000,@A5000));

위의 두 연결 방식 모두 8000을 반환합니다.

2. 주의사항+=

DECLARE @A VARCHAR(MAX) = '';

SET @A+= REPLICATE('A',5000) + REPLICATE('A',5000)

DECLARE @B VARCHAR(MAX) = '';

SET @B = @B + REPLICATE('A',5000) + REPLICATE('A',5000)


SELECT DATALENGTH(@A), 
       DATALENGTH(@B);`

돌아온다

-------------------- --------------------
8000                 10000

:@A렸습니니다다

발생하고 있는 문제를 해결하는 방법.

경우도 있습니다.max되거나 " 중"이기 때문입니다.varchar(4001 - 8000)으로 묶다nvarcharstring (짝수)nvarchar(max)를 참조해 주세요.

리터럴( ~ 리터럴 확인합니다.N.

첫 번째 문제를 방지하려면 에서 할당을 변경합니다.

DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;

로.

DECLARE @SQL NVARCHAR(MAX) = ''; 
SET @SQL = @SQL + N'Foo' + N'Bar'

이 되도록NVARCHAR(MAX)각도 접속의 입니다).NVARCHAR(MAX)★★★★★★★★★★★★★★★★)

볼 때 잘라내기 방지

"Results to grid" 모드가 선택되어 있는지 확인하고 다음을 사용할 수 있습니다.

select @SQL as [processing-instruction(x)] FOR XML PATH 

하면, SSMS 의 할 수 .XML★★★★★★processing-instruction는 음음음음음음음음음음음 bit bit bit bit bit bit bit bit bit bit bit 등의 합니다.<&lt;.

좋습니다. 나중에 문제가 되는 것은 쿼리가 허용 크기보다 크다는 것입니다(쿼리가 계속 증가할 경우 발생할 수 있음). 이를 청크로 분할하여 문자열 값을 실행해야 합니다.예를 들어 다음과 같은 저장 프로시저가 있다고 가정합니다.

CREATE PROCEDURE ExecuteMyHugeQuery
    @SQL VARCHAR(MAX) -- 2GB size limit as stated by Martin Smith
AS
BEGIN
    -- Now, if the length is greater than some arbitrary value
    -- Let's say 2000 for this example
    -- Let's chunk it
    -- Let's also assume we won't allow anything larger than 8000 total
    DECLARE @len INT
    SELECT @len = LEN(@SQL)

    IF (@len > 8000)
    BEGIN
        RAISERROR ('The query cannot be larger than 8000 characters total.',
                   16,
                   1);
    END

    -- Let's declare our possible chunks
    DECLARE @Chunk1 VARCHAR(2000),
            @Chunk2 VARCHAR(2000),
            @Chunk3 VARCHAR(2000),
            @Chunk4 VARCHAR(2000)

    SELECT @Chunk1 = '',
           @Chunk2 = '',
           @Chunk3 = '',
           @Chunk4 = ''

    IF (@len > 2000)
    BEGIN
        -- Let's set the right chunks
        -- We already know we need two chunks so let's set the first
        SELECT @Chunk1 = SUBSTRING(@SQL, 1, 2000)

        -- Let's see if we need three chunks
        IF (@len > 4000)
        BEGIN
            SELECT @Chunk2 = SUBSTRING(@SQL, 2001, 2000)

            -- Let's see if we need four chunks
            IF (@len > 6000)
            BEGIN
                SELECT @Chunk3 = SUBSTRING(@SQL, 4001, 2000)
                SELECT @Chunk4 = SUBSTRING(@SQL, 6001, (@len - 6001))
            END
              ELSE
            BEGIN
                SELECT @Chunk3 = SUBSTRING(@SQL, 4001, (@len - 4001))
            END
        END
          ELSE
        BEGIN
            SELECT @Chunk2 = SUBSTRING(@SQL, 2001, (@len - 2001))
        END
    END

    -- Alright, now that we've broken it down, let's execute it
    EXEC (@Chunk1 + @Chunk2 + @Chunk3 + @Chunk4)
END

당신은 nvarchar 텍스트도 사용합니다.즉, 거대한 문자열 앞에 단순히 "N"을 붙이면 끝! 더 이상 제한이 없습니다.

DELARE @SQL NVARCHAR(MAX);
SET @SQL = N'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO

받아들여진 답변이 도움이 되었지만, 사례 진술과 관련된 바샤를 연결하다가 넘어졌습니다.OP의 질문은 케이스 스테이트먼트에 관한 것이 아닌 것은 알지만, 케이스 스테이트먼트를 포함한 긴 다이내믹 SQL 스테이트먼트를 작성하는데 어려움을 겪고 있는 저와 같은 분을 위해 여기에 투고하는 것이 도움이 될 것이라고 생각했습니다.

문자열 연결과 함께 케이스 문을 사용할 경우 승인된 답변에서 언급된 규칙은 케이스 문장의 각 섹션에 독립적으로 적용됩니다.

declare @l_sql varchar(max) = ''

set @l_sql = @l_sql +
case when 1=1 then
    --without this correction the result is truncated
    --CONVERT(VARCHAR(MAX), '')
 +REPLICATE('1', 8000)
 +REPLICATE('1', 8000)
end

print len(@l_sql)
declare @p varbinary(max)
set @p = 0x
declare @local table (col text)

SELECT   @p = @p + 0x3B + CONVERT(varbinary(100), Email)
 FROM tbCarsList
 where email <> ''
 group by email
 order by email

 set @p = substring(@p, 2, 100000)

 insert @local values(cast(@p as varchar(max)))
 select DATALENGTH(col) as collen, col from @local

result collen > 8000, length col value is more than 8000 chars

언급URL : https://stackoverflow.com/questions/12639948/sql-nvarchar-and-varchar-limits

반응형