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
(여기에 표시)
질문의 다른 부분에 대해서
연결 시 잘라내는 방법은 데이터 유형에 따라 다릅니다.
varchar(n) + varchar(n)
.nvarchar(n) + nvarchar(n)
4000달러입니다.varchar(n) + nvarchar(n)
4000달러입니다.nvarchar
으로는 우선도가 됩니다.nvarchar(4,000)
[n]varchar(max)
+[n]varchar(max)
미만일 경우2GB는 잘리지 않습니다.varchar(max)
+varchar(n)
의 경우 (2GB의 경우)로 됩니다.varchar(max)
.varchar(max)
+nvarchar(n)
의 경우 (2GB의 경우)로 됩니다.nvarchar(max)
.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" 입니다.n
11로 .
새로운 구문 요소
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)
으로 묶다nvarchar
string (짝수)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 등의 합니다.<
<
.
좋습니다. 나중에 문제가 되는 것은 쿼리가 허용 크기보다 크다는 것입니다(쿼리가 계속 증가할 경우 발생할 수 있음). 이를 청크로 분할하여 문자열 값을 실행해야 합니다.예를 들어 다음과 같은 저장 프로시저가 있다고 가정합니다.
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
'programing' 카테고리의 다른 글
경고: push.default가 설정되지 않았습니다.Git 2.0에서 암묵적인 값이 변화하고 있습니다. (0) | 2023.04.21 |
---|---|
PowerShell을 사용하여 서브스트링 추출 (0) | 2023.04.21 |
bash 스크립트에서 루트로 실행 중인지 확인하는 방법 (0) | 2023.04.21 |
병합이 완료되지 않았습니다(MERGE_HEAD가 존재합니다). (0) | 2023.04.21 |
커밋을 푸시하기 위한https credential을 캐시하는 방법이 있습니까? (0) | 2023.04.21 |