Tôi hiểu rằng có 4000 bộ tối đa 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 ) ]
Ký |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 theo nghĩa đen max.
Nếu bạn chọn chỉ định một cụ thể nthì giá trị này phải nằm trong khoảng từ 1 đến 4.000 nhưng sử dụng maxxác định nó là một kiểu dữ liệu đối tượng lớn (thay thế cho kiểu dữ liệu ntextnày 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 , giới hạn 2GB có thể bị vượt quá 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 bớt 4.000 ký tự.
- varchar(n) + nvarchar(n)sẽ cắt bớt 4.000 ký tự.- nvarcharcó 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)đầu tiên sẽ chuyển đổi- varchar(n)đầu vào thành- nvarchar(n)và sau đó thực hiện nối. Nếu độ dài của- varchar(n)chuỗi lớn hơn 4.000 ký tự thì quá trình- nvarchar(4000)ép kiểu sẽ xảy ra 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 Ntiền tố và chuỗi là <= dài 4.000 ký tự nó sẽ được gõ là nvarchar(n)nơi nlà chiều 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 các Ntiền tố và chuỗi là <= dài 8.000 ký tự nó sẽ được gõ là varchar(n)nơi nlà chiều dài của chuỗi. Nếu còn như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. Các CONCATchức năng không giúp gì đâ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);`
Lợi nhuận
-------------------- --------------------
8000                 10000
Lưu ý rằng @Agặp phải sự cắt ngắn.
Cách giải quyết vấn đề bạn đang gặp phải.
Bạn đang bị cắt ngắn bởi vì bạn đang nối hai maxkiểu dữ liệu không phải với nhau hoặc vì bạn đang nối một varchar(4001 - 8000)chuỗi với một nvarcharchuỗ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 bài tập từ
DECLARE @SQL NVARCHAR(MAX);
SET @SQL = 'Foo' + 'Bar' + ...;
Đến
DECLARE @SQL NVARCHAR(MAX) = ''; 
SET @SQL = @SQL + N'Foo' + N'Bar'
để an NVARCHAR(MAX)tham gia vào quá trình nối ngay từ đầu (vì kết quả của mỗi lần nối cũng sẽ là NVARCHAR(MAX)điều này sẽ lan truyề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" rồi 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 XMLkết quả. Các processing-instructionchút tránh vấn đề với các nhân vật như <hiển thị như <.