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

Hỗ trợ UTF-8, SQL Server 2012 và UTF8String UDT

Tạo Loại tùy chỉnh do người dùng xác định thông qua SQLCLR là không , theo bất kỳ cách nào, sẽ giúp bạn thay thế bất kỳ loại bản địa nào. Nó rất tiện dụng để tạo thứ gì đó để xử lý dữ liệu chuyên dụng. Nhưng các chuỗi, thậm chí thuộc một bảng mã khác, không chuyên biệt. Đi theo lộ trình này cho dữ liệu chuỗi của bạn sẽ phá hủy mọi khả năng sử dụng của hệ thống, chưa kể đến hiệu suất vì bạn sẽ không thể sử dụng bất kỳ các hàm chuỗi tích hợp sẵn.

Nếu bạn có thể lưu bất cứ thứ gì trên dung lượng ổ đĩa, những lợi ích đó sẽ bị xóa bởi những gì bạn sẽ mất trong hiệu suất tổng thể. Việc lưu trữ một UDT được thực hiện bằng cách tuần tự hóa nó thành một VARBINARY . Vì vậy, để làm bất kỳ so sánh chuỗi HOẶC sắp xếp, bên ngoài so sánh "nhị phân" / "thứ tự", bạn sẽ phải chuyển đổi tất cả các giá trị khác, từng giá trị một, trở lại UTF-8 để sau đó thực hiện so sánh chuỗi có thể giải thích sự khác biệt về ngôn ngữ. Và việc chuyển đổi đó sẽ cần được thực hiện trong UDT. Điều này có nghĩa là, giống như kiểu dữ liệu XML, bạn sẽ tạo UDT để giữ một giá trị cụ thể, sau đó hiển thị một phương thức của UDT đó để chấp nhận một tham số chuỗi để thực hiện so sánh (tức là Utf8String.Compare(alias.field1) hoặc nếu xác định toán tử cho kiểu thì Utf8string1 = Utf8string2 và có = toán tử lấy chuỗi trong mã hóa UTF-8 và sau đó thực hiện CompareInfo.Compare() ).

Ngoài những cân nhắc ở trên, bạn cũng cần cân nhắc rằng việc chuyển các giá trị qua lại thông qua API SQLCLR có chi phí, đặc biệt là khi sử dụng NVARCHAR(MAX) hoặc VARBINARY(MAX) trái ngược với NVARCHAR(1 - 4000)VARBINARY(1 - 4000) tương ứng (vui lòng không nhầm lẫn sự phân biệt này với hàm ý bất kỳ điều gì về việc sử dụng SqlChars / SqlBytes so với SqlString / SqlBinary ).

Cuối cùng (ít nhất là về cách sử dụng UDT), vui lòng không xem qua thực tế rằng UDT đang được hỏi là mã mẫu . Thử nghiệm duy nhất được lưu ý là hoàn toàn về chức năng, không có gì xung quanh khả năng mở rộng hoặc "bài học kinh nghiệm sau khi làm việc với điều này trong một năm". Mã kiểm tra chức năng được hiển thị ở đây tại trang CodePlex sau và nên được xem trước khi tiếp tục với quyết định này vì nó cho biết bạn sẽ cần viết các truy vấn của mình như thế nào để tương tác với nó (điều này tốt cho một trường hoặc hai, nhưng không cho hầu hết / tất cả các trường chuỗi):

http://msftengprodsamples.codeplex.com /SourceControl/latest#Kilimanjaro_Trunk/Programmability/CLR/UTF8String/Scripts/Test.sql

Với số lượng cột và chỉ mục được tính toán liên tục được thêm vào, liệu có bất kỳ khoảng trống nào thực sự được tiết kiệm không?;-)

Khi không gian (đĩa, bộ nhớ, v.v.) là mối quan tâm, bạn có ba tùy chọn:

  1. Nếu bạn đang sử dụng SQL Server 2008 trở lên và đang sử dụng phiên bản Enterprise, thì bạn có thể bật Nén dữ liệu . Nén dữ liệu có thể (nhưng không phải "luôn luôn") nén dữ liệu Unicode trong NCHARNVARCHAR lĩnh vực. Các yếu tố quyết định là:

    1. NCHAR(1 - 4000)NVARCHAR(1 - 4000) sử dụng Lược đồ nén chuẩn cho Unicode , nhưng chỉ bắt đầu trong SQL Server 2008 R2 VÀ chỉ cho dữ liệu IN ROW, không phải OVERFLOW! Điều này có vẻ tốt hơn so với thuật toán nén ROW / PAGE thông thường.
    2. NVARCHAR(MAX)XML (và tôi cũng đoán là VARBINARY(MAX) , TEXTNTEXT ) dữ liệu IN ROW (không nằm ngoài hàng trong các trang LOB hoặc OVERFLOW) có thể được nén ít nhất PAGE và có thể ROW cũng được nén (không chắc chắn về cái cuối cùng này).
    3. Mọi dữ liệu ROW TẮT, LOB hoặc OVERLOW =Bạn không cần nén!
  2. Nếu sử dụng phiên bản cũ hơn 2008 hoặc không phải trên Enterprise Edition, bạn có thể có hai trường:một VARCHAR và một NVARCHAR . Ví dụ:giả sử bạn đang lưu trữ các URL chủ yếu là tất cả các ký tự ASCII cơ bản (giá trị 0 - 127) và do đó phù hợp với VARCHAR , nhưng đôi khi có các ký tự Unicode. Lược đồ của bạn có thể bao gồm 3 trường sau:

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );
    

    Trong mô hình này, bạn chỉ CHỌN từ [URL] cột được tính toán. Để chèn và cập nhật, bạn xác định trường nào sẽ sử dụng bằng cách xem việc chuyển đổi có làm thay đổi giá trị đến hay không, giá trị này phải là NVARCHAR loại:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
    
  3. Nếu bạn có các trường chỉ nên có các ký tự phù hợp với Trang mã cụ thể của bộ ký tự ASCII mở rộng, thì chỉ cần sử dụng VARCHAR .

P.S. Chỉ cần nêu rõ điều này:_SC mới Các đối chiếu được giới thiệu trong SQL Server 2012 chỉ cho phép:

  • các chức năng tích hợp để xử lý đúng các Ký tự bổ sung / Các cặp thay thế và
  • quy tắc ngôn ngữ cho các Ký tự bổ sung được sử dụng để sắp xếp và so sánh

Tuy nhiên, ngay cả khi không có _SC mới Đối chiếu, bạn vẫn có thể lưu trữ bất kỳ ký tự Unicode nào thành XML hoặc N - loại đã sửa trước, và truy xuất nó mà không mất dữ liệu. Tuy nhiên, khi sử dụng các Ảnh ghép cũ hơn (tức là không có số phiên bản trong tên), tất cả các Ký tự bổ sung đều tương đương với nhau. Bạn cần sử dụng _90_100 Các đối chiếu ít nhất giúp bạn so sánh và phân loại điểm nhị phân / điểm mã; chúng không thể tính đến các quy tắc ngôn ngữ vì chúng không có ánh xạ cụ thể của các Ký tự bổ sung (và do đó không có trọng số hoặc quy tắc chuẩn hóa).

Hãy thử những cách sau:

IF (N'𤪆' = N'𤪆') SELECT N'𤪆' AS [TheLiteral], NCHAR(150150) AS [Generated];
IF (N'𤪆' = N'𤪇') SELECT N'𤪇' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'𤪆' COLLATE Tatar_90_CI_AI = N'𤪇' COLLATE Tatar_90_CI_AI)
       SELECT N'𤪇 COLLATE Tatar_90_CI_AI' AS [TheLiteral], NCHAR(150151) AS [Generated];
IF (N'𤪆' = N'?') SELECT N'?';

Trong DB có một đối chiếu mặc định kết thúc bằng _SC , chỉ IF đầu tiên câu lệnh sẽ trả về một tập hợp kết quả và trường "Đã tạo" sẽ hiển thị các ký tự một cách chính xác.

Nhưng, nếu DB không có đối chiếu mặc định kết thúc bằng _SC và đối chiếu không phải là _90 hoặc _100 đối chiếu chuỗi, sau đó là hai IF đầu tiên câu lệnh trả về tập hợp kết quả trong đó trường "Đã tạo" sẽ trả về NULL và trường "Chữ" hiển thị chính xác.

Đối với dữ liệu Unicode, Đối chiếu không liên quan đến lưu trữ vật lý.

CẬP NHẬT 2018-10-02

Mặc dù đây chưa phải là một tùy chọn khả thi, nhưng SQL Server 2019 giới thiệu hỗ trợ gốc cho UTF-8 trong VARCHAR / CHAR Loại dữ liệu. Hiện tại có quá nhiều lỗi để nó được sử dụng, nhưng nếu chúng được sửa thì đây là một tùy chọn cho một số các tình huống. Vui lòng xem bài đăng của tôi, " Hỗ trợ UTF-8 gốc trong SQL Server 2019:Vị cứu tinh hay nhà tiên tri sai? ", để có phân tích chi tiết về tính năng mới này.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ngày làm việc đầu tiên của tháng hiện tại - SQL Server

  2. Cách tạo cơ sở dữ liệu trong SQL Server

  3. Làm thế nào để bạn lập mô hình kế thừa trong cơ sở dữ liệu một cách hiệu quả?

  4. Invoke-Sqlcmd:Đã xảy ra lỗi liên quan đến mạng hoặc trường hợp cụ thể khi thiết lập kết nối với SQL Server

  5. Vị trí thực của dữ liệu FILESTREAM