2010-09-27 29 views
12

Trong một trường hợp thử nghiệm tôi đã viết, so sánh chuỗi không xuất hiện để làm việc theo cùng một cách giữa SQL server/.NET CLR.Sự khác nhau về chuỗi so sánh giữa .NET và T-SQL?

Mã này C#:

string lesser = "SR2-A1-10-90"; 
string greater = "SR2-A1-100-10"; 

Debug.WriteLine(string.Compare("A","B")); 
Debug.WriteLine(string.Compare(lesser, greater)); 

Will đầu ra:

-1 
1 

này mã SQL Server:

declare @lesser varchar(20); 
declare @greater varchar(20); 

set @lesser = 'SR2-A1-10-90'; 
set @greater = 'SR2-A1-100-10'; 

IF @lesser < @greater 
    SELECT 'Less Than'; 
ELSE 
    SELECT 'Greater than'; 

Will đầu ra:

Less Than 

Tại sao lại có sự khác biệt?

+0

Bạn có tính toán phân biệt chữ hoa chữ thường không? –

+0

Các trường hợp giống nhau. Sự khác biệt là cách xử lý '0' đến '-'. –

+0

Đây là một vấn đề Unicode tôi nghĩ. Chỉnh sửa: Có thể không. Đối với tôi, mã SQL Server trả về 'Lớn hơn'. Collation mặc định trong cơ sở dữ liệu bạn đang thử nghiệm nó là gì? –

Trả lời

10

Đây là documented here.

Ghép Windows (ví dụ: Latin1_General_CI_AS) sử dụng quy tắc đối chiếu loại Unicode. SQL Collations không.

Điều này khiến ký tự gạch nối được xử lý khác nhau giữa hai ký tự.

+0

chọn * từ fn_helpcollations() nơi tên như '% SQL_Latin1_General_CP1_CI_AS%' hoặc name = 'Latin1_General_CI_AS' – gbn

+0

Loại không phải unicode là khác nhau, sử dụng CP 1252. Tôi chắc chắn LATIN1 .. cũng vậy ... không có nó không .. http://msdn.microsoft.com/en-us/library/ms143515.aspx – gbn

3
  • Trong SQL bạn dùng varchar đó là cơ bản ASCII (tùy thuộc vào đối chiếu) mà sẽ cung cấp - trước 0
  • Trong C# tất cả các chuỗi là Unicode

Các điểm tốt hơn của UTF-xx (C#) vs UCS-2 (SQL Server) khá phức tạp.

Edit:

tôi gửi quá sớm

tôi nhận được "Lớn hơn" trên SQL Server 2008 với Latin1_General_CI_AS chiếu

Chỉnh sửa 2:

Tôi cũng muốn thử SELECT ASCII(...) trên của bạn dấu gạch ngang. Ví dụ: nếu đoạn mã SQL đã từng nằm trong tài liệu Word - (150) không phải là - (45) tôi đã sao chép vào SQL Server để kiểm tra trình duyệt của tôi khỏi các câu hỏi của bạn. Xem CP 1252 (= CP1 = SQL Server lingo)

Chỉnh sửa 3: Xem câu trả lời của Martin Smith: 2 collations có thứ tự sắp xếp khác nhau.

+0

Ah, tôi hiểu rồi. Khi tôi sử dụng nvarchar (20), tôi nhận được 'Greater Than'. –

+0

Tôi nhận được điều này với varchar. DB của bạn collation khác với Server collation? – gbn

7

Ngoài câu trả lời của gbn, bạn có thể làm cho chúng hoạt động giống nhau bằng cách sử dụng CompareOptions.StringSort trong C# (hoặc bằng cách sử dụng StringComparison.Ordinal). Điều này xử lý các ký hiệu khi xảy ra trước ký hiệu chữ và số, do đó "-" < "0".

Tuy nhiên, Unicode vs ASCII không giải thích bất cứ điều gì, vì mã hex cho mã ASCII được dịch nguyên văn sang mã Unicode: "-" là 002D (45) trong khi "0" là 0030 (48). .NET đang sử dụng phân loại "ngôn ngữ" theo mặc định, dựa trên thứ tự và trọng số phi thứ tự được áp dụng cho các ký hiệu khác nhau theo văn hóa được chỉ định hoặc hiện tại. Thuật toán ngôn ngữ này cho phép, ví dụ "résumé" (viết bằng dấu) xuất hiện ngay sau "resume" (viết không có dấu) trong danh sách sắp xếp các từ, vì "é" được đưa ra một thứ tự phân số ngay sau "e" và trước khi "f". Nó cũng cho phép "hợp tác" và "hợp tác" được đặt chặt chẽ với nhau, như biểu tượng dấu gạch ngang được cho thấp "trọng lượng"; nó chỉ quan trọng như là các bộ ngắt cuối cùng tuyệt đối khi sắp xếp các từ như "bit", "bit" và "bit-shift" (sẽ xuất hiện theo thứ tự đó).

Được gọi là sắp xếp thứ tự (theo đúng giá trị Unicode, có hoặc không có phân biệt chữ hoa chữ thường) sẽ tạo ra kết quả rất khác nhau và đôi khi phi logic, vì các biến thể của chữ thường xuất hiện tốt sau bảng chữ cái Latin chưa được đặt trước. trong khi các ký hiệu xuất hiện trước nó. Ví dụ: "é" xuất hiện sau "z" và do đó các từ "tiếp tục", "rosin", "rúp", "sơ yếu lý lịch" sẽ được sắp xếp theo thứ tự đó. "Bit's", "Bit-shift", "Biter", "Bits" sẽ được sắp xếp theo thứ tự như dấu nháy đơn đến trước, theo sau là dấu gạch ngang, sau đó là chữ "e", sau đó là chữ "s". Không phải điều này có vẻ hợp lý từ góc độ "ngôn ngữ tự nhiên".

+0

Trang mã chỉ ảnh hưởng đến ký tự> 127, không? – gbn

+0

Tuyệt. Bằng cách sử dụng 'CompareOption.StringSort', tôi có thể chạy thử nghiệm của mình, với các cài đặt đối chiếu cơ sở dữ liệu hiện tại. –

+0

@gbn - Về mặt kỹ thuật có. Nó cũng C# mà dường như được phân loại "sai"; mà không có StringSort, ký tự ký hiệu xuất hiện sau chữ và số. Tôi sẽ chỉnh sửa. – KeithS

0

Một số câu trả lời tuyệt vời đã xảy ra tại sao điều này xảy ra, nhưng tôi chắc rằng những người khác chỉ muốn biết mã C# để lặp lại bộ sưu tập theo thứ tự như máy chủ SQL. Tôi đã tìm thấy các công trình sau đây tốt nhất. "Ordinal" được xung quanh vấn đề dấu gạch nối trong khi "IgnoreCase" dường như cũng phản ánh mặc định của máy chủ SQL.

Debug.WriteLine(string.Compare(lesser, greater, StringComparison.OrdinalIgnoreCase)); 
Các vấn đề liên quan