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ể n
thì giá trị này phải nằm trong khoảng từ 1 đến 4.000 nhưng sử dụng max
xác định nó là một kiểu dữ liệu đối tượng lớn (thay thế cho kiểu dữ liệu ntext
nà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ự. 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)
đầ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 N
tiền tố và chuỗi là <= dài 4.000 ký tự nó sẽ được gõ là nvarchar(n)
nơi n
là 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 N
tiền tố và chuỗi là <= dài 8.000 ký tự nó sẽ được gõ là varchar(n)
nơi n
là 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 CONCAT
chứ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 @A
gặ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 max
kiể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 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 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 XML
kết quả. Các processing-instruction
chút tránh vấn đề với các nhân vật như <
hiển thị như <
.