Tôi hiểu rằng có bộ tối đa 4000 cho
NVARCHAR(MAX)
Sự hiểu biết của bạn là sai. nvarchar(max)
có thể lưu trữ tối đa (và đôi khi cao hơn) 2GB dữ liệu (1 tỷ ký tự byte kép).
Từ nchar và nvarchar trong Sách trực tuyến, ngữ pháp là
nvarchar [ ( n | max ) ]
|
nhân vật có nghĩa là đây là những lựa chọn thay thế. tức là bạn chỉ định một trong hai n
hoặc chữ max
.
Nếu bạn chọn chỉ định một n
cụ thể thì giá trị này phải từ 1 đến 4.000 nhưng sử dụng max
định nghĩa nó như một kiểu dữ liệu đối tượng lớn (thay thế cho ntext
không được dùng nữa).
Trên thực tế, trong SQL Server 2008, có vẻ như đối với một biến có thể vượt quá giới hạn 2GB vô thời hạn tùy thuộc vào đủ dung lượng trong tempdb
(Hiển thị tại đây)
Về các phần khác của câu hỏi của bạn
Việc cắt bớt khi nối phụ thuộc vào kiểu dữ liệu.
-
varchar(n) + varchar(n)
sẽ cắt ngắn ở 8.000 ký tự. -
nvarchar(n) + nvarchar(n)
sẽ cắt ngắn còn 4.000 ký tự. -
varchar(n) + nvarchar(n)
sẽ cắt bớt 4.000 ký tự.nvarchar
có mức độ ưu tiên cao hơn nên kết quả lànvarchar(4,000)
-
[n]varchar(max)
+[n]varchar(max)
sẽ không cắt bớt (cho <2GB). -
varchar(max)
+varchar(n)
sẽ không cắt bớt (đối với <2GB) và kết quả sẽ được nhập làvarchar(max)
. -
varchar(max)
+nvarchar(n)
sẽ không cắt bớt (đối với <2GB) và kết quả sẽ được nhập lànvarchar(max)
. -
nvarchar(max)
+varchar(n)
trước tiên sẽ chuyển đổivarchar(n)
nhập vàonvarchar(n)
và sau đó thực hiện nối. Nếu độ dài củavarchar(n)
chuỗi lớn hơn 4.000 ký tự thì truyền sẽ thànhnvarchar(4000)
và việc cắt ngắn sẽ xảy ra .
Các kiểu dữ liệu của chuỗi ký tự
Nếu bạn sử dụng N
tiền tố và chuỗi dài <=4.000 ký tự, nó sẽ được nhập là nvarchar(n)
ở đâu n
là độ dài của chuỗi. Vì vậy, N'Foo'
sẽ được coi là nvarchar(3)
Ví dụ. Nếu chuỗi dài hơn 4.000 ký tự, nó sẽ được coi là nvarchar(max)
Nếu bạn không sử dụng N
tiền tố và chuỗi dài <=8.000 ký tự, nó sẽ được nhập là varchar(n)
ở đâu n
là độ dài của chuỗi. Nếu dài hơn varchar(max)
Đối với cả hai điều trên nếu độ dài của chuỗi bằng 0 thì n
được đặt thành 1.
Các phần tử cú pháp mới hơn.
1. CONCAT
chức năng không hữu ích ở đây
DECLARE @A5000 VARCHAR(5000) = REPLICATE('A',5000);
SELECT DATALENGTH(@A5000 + @A5000),
DATALENGTH(CONCAT(@A5000,@A5000));
Ở trên trả về 8000 cho cả hai phương pháp nối.
2. Hãy cẩn thận với +=
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);`
Trả lại
-------------------- --------------------
8000 10000
Lưu ý rằng @A
gặp phải sự cắt ngắn.
Cách giải quyết sự cố bạn đang gặp phải.
Bạn đang bị cắt bớt vì bạn đang ghép hai không max
các kiểu dữ liệu với nhau hoặc do bạn đang nối varchar(4001 - 8000)
chuỗi thành một nvarchar
chuỗi đã nhập (chẵn nvarchar(max)
).
Để tránh vấn đề thứ hai, chỉ cần đảm bảo rằng tất cả các ký tự chuỗi (hoặc ít nhất là những ký tự có độ dài trong phạm vi 4001 - 8000) được mở đầu bằng N
.
Để tránh vấn đề đầu tiên, hãy thay đổi nhiệm vụ từ
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
Tới
DECLARE @SQL NVARCHAR(MAX) = '';
SET @SQL = @SQL + N'Foo' + N'Bar'
sao cho NVARCHAR(MAX)
tham gia vào quá trình nối ngay từ đầu (vì kết quả của mỗi lần ghép cũng sẽ là NVARCHAR(MAX)
điều này sẽ phổ biến)
Tránh cắt ngắn khi xem
Đảm bảo rằng bạn đã chọn chế độ "kết quả thành lưới" thì bạn có thể sử dụng
select @SQL as [processing-instruction(x)] FOR XML PATH
Các tùy chọn SSMS cho phép bạn đặt độ dài không giới hạn cho XML
các kết quả. processing-instruction
bit tránh các sự cố với các ký tự như <
hiển thị dưới dạng <
.