Мы замечаем странное поведение в нашем приложении относительно параметров связывания.Мы используем Java с JDBC для подключения к базе данных Sql Server.В ячейке таблицы у нас есть значение «µ», и мы сравниваем его с параметром связывания, который также имеет значение «µ».
Теперь в SQL-выражении типа "... где значение! =?" , где 'значение' - это значение 'µ' в базе данных и?переменная связывания, которая также установлена в «µ», мы замечаем, что получаем запись, хотя мы ожидаем, что «µ» будет равняться «µ».
Метод, который мы используем для заполнения параметра связыванияis java.sql.PreparedStatement.setString (int, String).
Некоторые факты:
Символьное значение µ в разных кодировках:
ASCII (ISO-8859-1) : 0xB5
UTF-8 : 0xC2B5
UTF-16 (= Java) : 0x00B5
Теперь я провел несколько исследований, чтобы выяснить, какие байты база данных действительно видит.Для этого я попробовал SQL-выражение следующим образом:
select convert(VARBINARY(MAX), value), -- selects µ from database table
convert(VARBINARY(MAX), N'µ'), -- selects µ from literal
convert(VARBINARY(MAX), ?) -- selects µ from bind parameter
from ...
Результат для трех значений:
B500
B500
C200B500 <-- Here is the problem!
Итак, внутреннее представление µ в базе данных и как литерал NVARCHARэто B500.
Теперь мы не можем понять, что здесь происходит.У нас есть значение «µ» в переменной Java (которое должно быть внутренне 0x00B5).Когда она передается как переменная связывания, то создается впечатление, что она преобразована в UTF-8 (что делает последовательность байтов 0xC2B5), и затем база данных обрабатывает ее, как если бы это были два символа, делая из нее последовательность символов C200B500.
Чтобы сделать вещи еще более запутанными:
(1) На другой машине с другой базой данных тот же код работает, как и ожидалось.Результатом трех строк является B500 / B500 / B500, поэтому переменная связывания преобразуется в правильный B500.
(2) На той же машине, той же базе данных, но другой программе (но с использованиемта же библиотека драйверов jdbc и те же параметры подключения) этот также работает как положено, что дает результат B500 / B500 / B500.
Некоторые дополнительные факты, возможно, они важны: База данныхSql Server 2014 Java - Java 7 Рассматриваемое приложение - это веб-приложение, работающее на Tomcat 7. Jdbc-библиотека - sqljdbc 4.2
Любая помощь для решения этой проблемы очень ценится!