Несмотря на то, что принятый ответ работает и является верным в отношении того, что основная проблема заключается в «широких» символах, в Вопросе есть несколько неправильных представлений и технических аспектов, которые следует рассмотреть, чтобы лучшепонимание того, что на самом деле происходит здесь, как в .NET, так и в SQL Server.
Первый:
У меня есть две строки, одна с двойнымзначение байта, а другой - один байт-один.
Нет, вы не делаете.У вас есть две строки Unicode, закодированные как UTF-16 Little Endian (так работают все Windows и .NET).И хотя с практической точки зрения, в большинстве случаев символы являются двухбайтовыми, они охватывают только 62 000 - 63 000 (или около того) символов (т. Е. Кодовые точки между U + 0000 и U + FFFF - или 0 - 65 535), чтоявляются "действительными" символами).Но Unicode позволяет отображать чуть более 1,1 миллиона кодовых точек, и в настоящее время уже более 260 000 из этих кодовых точек уже сопоставлены .Точки кода выше U + FFFF / 65 535, известные как дополнительные символы, отображаются на наборы из двух двухбайтовых значений, известных как суррогатные пары.Поэтому, хотя они используются реже, большинство кодовых точек Unicode на самом деле составляют 4 байта.
Секунда:
Результат сравнения строк возвращает false, какя могу заставить их сравнивать правильно
Буквы в s1 = "smatsumoto11"
известны как символы "Fullwidth".Вы можете увидеть их полный список здесь:
http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:East_Asian_Width=Fullwidth:]
Некоторое объяснение, почему в первую очередь существуют разные ширины, можно найти здесь:
http://unicode -table.com / ru / blocks / halfwidth-and-fullwidth-forms /
Если вы хотите сравнить две строки в вопросе так, чтобы они были равны, вы можетелибо используйте метод String.Compare (String, String, CultureInfo, CompareOptions) , как указано в ответе @ Arnout, либо используйте CompareInfo.Compare (String, String, CompareOptions) какследует:
CompareInfo.Compare(s1, s2, CompareOptions.IgnoreWidth)
Третье:
В том же сценарии, если у вас есть столбец nvarchar в SQL-сервере, который содержит значение smatsumoto11, запросдля извлечения данных с условием where, содержащим строку smatsumoto11, будет возвращаться та же строка.
Это потенциально опасный способ думать о сравнении строк.Нет особого способа сравнения строк практически в любой базе данных, если только строки не находятся в 7-битном ASCII (значения 0–127), который даже не включает кодовые страницы, и я не знаю, является ли это вообще опцией,Сравнения основаны на конкретной LCID / Locale / Culture / Collation.Параметры сортировки по умолчанию в SQL Server (по крайней мере, в США): SQL_Latin1_General_CP1_CI_AS
, что не учитывает регистр и не учитывает акцент.Он также использует кодовую страницу 1252 (которая влияет на данные CHAR / VARCHAR, а не NCHAR / NVARCHAR) и культуру "en-US".Параметры сортировки для других культур / LCID могут не совпадать с полной шириной и «полушириной».Кроме того, параметры сортировки, в имени которых указано _WS
, определенно не будут приравнивать эти две строки, поскольку _WS
означает "чувствительный к ширине", который является значением по умолчанию для сравнения .NET, если вы не указали параметр CompareOptions.IgnoreWidth
.
Если вы выполните следующий запрос, чтобы найти сопоставления с _WS
в названии, вы обнаружите, что из общего числа сопоставлений 1776 из 1785 сопоставлений, которые чувствительны к ширине, не соответствовать этим двум строкам (по крайней мере, в SQL Server 2012).Конечно, есть также 262 двоичных сопоставления (т. Е. Имена, заканчивающиеся либо устаревшими _BIN
, либо предпочтительными _BIN2
), которые также не будут приравнивать эти строки, но это не является проблемой чувствительности к ширине.
SELECT *
FROM sys.fn_helpcollations()
WHERE [name] LIKE N'%[_]WS%'
ORDER BY [name];
-- 1776 out of 3885 on SQL Server 2012
Кроме того, как я только что упомянулd, неудачное (и устарело) сопоставление по умолчанию SQL_Latin1_General_CP1_CI_AS
или даже лучшая версия Latin1_General_100_CI_AS
не чувствительна к регистру. Таким образом, все сравниваемые строки являются строчными, поэтому они равны при использовании только CompareOptions.IgnoreWidth
, но если вы хотите эмулировать эти конкретные параметры сортировки в SQL Server, поведение по умолчанию .NET с учетом регистра не будет соответствовать поведение SQL Server. Чтобы лучше соответствовать поведению SQL Server (по крайней мере, для тех сопоставлений или любых помеченных как имеющие _CI
и , а не имеющих _WS
, вам также необходимо включить параметр CompareOptions.IgnoreCase
следующим образом: 1075 *
CompareInfo.Compare(s1, s2, CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase)
// or
String.Compare(s1, s2, CultureInfo.CurrentCulture,
CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase)
Дополнительные ресурсы:
Сравнение строк в .NET Framework
Рекомендации по использованию строк в .NET Framework