Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Các giới hạn NVARCHAR và VARCHAR trong SQL

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.

  1. varchar(n) + varchar(n) sẽ cắt ngắn ở 8.000 ký tự.
  2. nvarchar(n) + nvarchar(n) sẽ cắt ngắn còn 4.000 ký tự.
  3. 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)
  4. [n]varchar(max) + [n]varchar(max) sẽ không cắt bớt (cho <2GB).
  5. 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) .
  6. 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) .
  7. nvarchar(max) + varchar(n) trước tiên sẽ chuyển đổi varchar(n) nhập vào 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ì truyền sẽ thành nvarchar(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 &lt; .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tham chiếu bí danh ở nơi khác trong danh sách CHỌN

  2. Vòng lặp SQL Server - làm cách nào để tôi lặp qua một tập hợp các bản ghi

  3. Cách lấy OBJECT_NAME () từ Cơ sở dữ liệu khác trong SQL Server

  4. Cú pháp không chính xác gần ')' gọi thủ tục được lưu trữ với GETDATE

  5. Cách duy trì thứ tự chèn trong SQL Server