|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
Подскажите пожалуйста с казалось бы простым вопросом. У меня есть БД с COLLATE Turkish_CI_AS, установлен SQL Server с этой БД на машине, где системная ACP=1251 (кириллица, Русский), есть таблица TABLE t(v TEXT) - эти настройки я менять не могу! Задача записывать/считывать строки с этой БД, учитывая что они будут только турецкими. Использую SQL Server 2014, ADO, провайдеры Native Client и также пробовал OLE DB Driver for SQL Server. В connection string "Auto Translate=False". И клиент и сервер на одной машине для теста. 1. Сначала пробую записать в БД турецкую строку (и это работает правильно!): ADO Connection->Execute(L"INSERT INTO t VALUES(\'çalışan\')"), передаю это все как Unicode-строку и проблем не возникает: в .mdf-файле вижу, что есть строка "çalışan", записанная в кодировке 1254 (Turkish)! Т.е. сервер преобразовал Unicode в турецкую кодировку правильно и записал как строку типа TEXT (не Unicode) в базу. 2. Пробую считать строку через sqlcmd: sqlcmd -Q "SELECT * FROM t" -u -o "output.txt" на выходе получаю Unicode-файл, в котором строка "çalışan". Все супер! 3. А теперь пробую через ADO выполнить этот же SELECT самостоятельно, в результате получаю в variant Field.Value типа BSTR, в котором строка "зalэюan". Т.е. провайдер взял и передал все в кодировке 1254 однобайтными символами, а затем эти байты преобразовал это в Unicode используя 1251! Бред полнейший. Хотя должен по логике просто преобразовать в Unicode, используя 1254. Если же ставить Auto Translate=True, то получаю строку "cal?san" - ну здесь все понятно и так и должно быть (преобразование из 1254 в Unicode, а затем в 1251). Как заставить ADO рабоать правильно в данном случае? Спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 12:19 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1, TEXT - это не юникодный тип, нужен NTEXT (а лучше NVARCHAR(max)) Попробуйте сконвертировать к юникодному типу в самом запросе Код: sql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 12:49 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
Я прекрасно понимаю, что TEXT-не юникод, но ADO возвращает все данные Field.Value в unicode BSTR и почему-то делает это неправильно. Хотя sqlcmd при тех же условиях и тех же запросах делает все верно! У меня тысячи запросов и я не могу везде ставить cast() - это неправильно. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:03 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 У меня тысячи запросов и я не могу везде ставить cast() - это неправильно. Вы попробовали и это помогает? Можно же вашу таблицу во вью обернуть. А в ADO нельзя явно указать тип поля? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:10 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
msLex victorov1 У меня тысячи запросов и я не могу везде ставить cast() - это неправильно. Вы попробовали и это помогает? Можно же вашу таблицу во вью обернуть. А в ADO нельзя явно указать тип поля? Да, это помогает конечно, также как и работа с NTEXT, NVARCHAR, но это не тот путь, которым нужно идти. Таблиц много и я должен корректно обрабатывать запросы типа SELECT * FROM даже если там не-юникод строки. Вопрос в том - почему ADO возвращает Unicode BSTR неправильно сконвертированный в юникод из кодировки БД? И как sqlcmd это делает корректно? Про указания типа поля ADO ничего не нашел. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:25 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 Вопрос в том - почему ADO возвращает Unicode BSTR неправильно сконвертированный в юникод из кодировки БД? И как sqlcmd это делает корректно? Про указания типа поля ADO ничего не нашел. Думаю, эффективнее будет спросить на форуме по конкретной платформе разработки (Delphi, .Net или что там у вас). ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:31 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 Т.е. провайдер взял и передал все в кодировке 1254 однобайтными символами, а затем эти байты преобразовал это в Unicode используя 1251! Бред полнейший. 1.Хотя должен по логике просто преобразовать в Unicode, используя 1254. 2.Как заставить ADO рабоать правильно в данном случае? 1. Ваша логика - не совсем правильная. Ежели вы напряжете мозг - поймте почему. 2. Хотите Юникод - преобразуйте в юникод. select cast(v as NTEXT) as v from [есть таблица TABLE]; ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:40 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:46 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно? Хотите "как есть" - преобразуйте к binary. select cast(v as varbinary(max)) as v from [есть таблица TABLE]; ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:49 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
только не меняя SQL-запрос! SELECT * FROM anytable я хочу чтобы если тип строки adChar, adLongVarChar, adVarChar, я бы получал в Field.Value вариант с типом VT_LPSTR ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:52 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 только не меняя SQL-запрос! SELECT * FROM anytable я хочу чтобы если тип строки adChar, adLongVarChar, adVarChar, я бы получал в Field.Value вариант с типом VT_LPSTR Хотеть никто не запрещает. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:54 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
утилиты sqlcmd, osql корректно отображают данные при таком запросе ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 13:59 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 утилиты sqlcmd, osql корректно отображают данные при таком запросе И? Ты могешь профайлером осмотреть чудесный запрос, который sqlcmd выполняет на сервере. ЗЫ. Сревер телепатии не обучен. select v from aTable; возвращает, например, три байта 1, 2, 3 откуда ADO должно понять, что это турецкие символы? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 14:11 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 но это не тот путь, которым нужно идти. На "не тот путь" ты свернул ещё когда поставил турецкую базу на сервер с русским ANSI. всё остальное - следствия. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 15:21 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
aleks222 victorov1 утилиты sqlcmd, osql корректно отображают данные при таком запросе откуда ADO должно понять, что это турецкие символы? а вот отсюда сервер должен понять - COLLATE Turkish_CI_AS . Проблема в том, что в ту сторону (от клиент к серверу) все работает правильно - я делаю INSERT в БД Юникод строкой с турецкими символами и сервер зная что кодировка БД 1254 предобразовывает Unicode->ANSI 1254. Все правильно. А вот в обратную сторону почему он де делает того же преобразования ANSI 1254->Unicode. Почему? Вместо этого он (или ADO на клиенте) конвертит байты из 1251 в Unicode и дает мне такую вот Unicode строку в Field.Value. На "не тот путь" ты свернул ещё когда поставил турецкую базу на сервер с русским ANSI. Где написано что так нельзя? Тем более это у заказчика, я не могу там что-то менять. А работать должно. И может, как видно по утилитам sqlcmd. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 15:30 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
у как выглядит у вас строка соединения для ADO? какой вы провайдер используете? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:10 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
попробуйте ODBC драйвер, там есть настройка языка ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:13 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
пробовал три првайдера - Native Client, SQL ODBC Driver For SQL Server и старый OLEDB.1 - результат одинаковый. Настройки языка там крутил - но они только для текста ошибок Судя по описанию должно работать Auto Translate=False, но вот как-то не так работает... ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:28 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 пробовал три првайдера - Native Client, SQL ODBC Driver For SQL Server и старый OLEDB.1 - результат одинаковый. Настройки языка там крутил - но они только для текста ошибок Судя по описанию должно работать Auto Translate=False, но вот как-то не так работает... С какого "описания" вы это взяли? Что "Auto Translate=true" - должно перевести с турецкого на олбанский? Еще раз: 1, 2, 3 никак не идентифицируются "как турецкие". Про collation знает только сервер. Либо вы конвертируете ascii в юникод на сервере, который знает, что это турецкий. Либо получаете байты на клиенте и САМИ конвертируете в турецкий юникод. Либо никак. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 16:44 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1, https://docs.microsoft.com/ru-ru/sql/relational-databases/native-client/applications/using-connection-string-keywords-with-sql-server-native-client?view=sql-server-ver15 AutoTranslate Если имеет значение «yes» , строки символов ANSI, которыми обмениваются клиент и сервер, переводятся с использованием Юникода, чтобы минимизировать проблемы сопоставления символов национальных алфавитов кодовых страниц клиента и сервера. Клиентские SQL_C_CHAR данные, отправляемые в SQL Server переменную типа char, varchar или Text , параметр или столбец, преобразуются из символов в Юникод с помощью клиентской кодовой страницы ANSI (ACP), а затем преобразуются из Юникода в символьный с помощью ACP сервера. SQL Serverданные типа char, varchar или Text , отправленные в переменную клиента SQL_C_CHAR, преобразуются из символа в Юникод с помощью ACP сервера, а затем преобразуются из Юникода в символьный с помощью клиента ACP. Эти преобразования выполняются на клиенте драйвером ODBC собственного клиента SQL Server. Для этого необходимо, чтобы на сервере была доступна такая же кодовая страница ANSI , какая используется на клиенте . Следующие параметры не влияют на преобразования, выполняемые для этих передач. * Юникод SQL_C_WCHAR данные клиента, отправляемые на сервер char, varchar или Text . * данные типа char, varchar или Text Server, отправленные в переменную SQL_C_WCHAR Юникод на клиенте. * ANSI SQL_C_CHAR клиентские данные, отправленные в Юникоде nchar, nvarchar или ntext на сервере. * Данные в Юникоде nchar, nvarchar или ntext , отправленные в переменную SQL_C_CHAR ANSI на клиенте. Если имеет значение «no», перевод символов не выполняется. SQL ServerДрайвер ODBC для собственного клиента не преобразует клиентский символ ANSI SQL_C_CHAR данные, отправляемые в переменные char, varchar или Text , параметры или столбцы на сервере. Не выполняется перевод данных типа char, varchar или Text , отправляемых с сервера, в SQL_C_CHAR переменные на клиенте. Если клиент и SQL Server используют разные кодовые страницы ANSI, символы национального алфавита могут быть переведены неправильно. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:04 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
aleks222 С какого "описания" вы это взяли? Что "Auto Translate=true" - должно перевести с турецкого на олбанский? Я как раз говорю что нужно использовать Auto Translate=False, чтобы не было неправильных преобразований (см. ниже мой тест) aleks222 Либо получаете байты на клиенте и САМИ конвертируете в турецкий юникод. Как это сделать? Повторюсь, ADO возвращает только UNICODE-строки в Field.Value (VT_BSTR), а получить строку с однобайтныйми символами VT_LPSTR мне не удалось никак! Решение я нашел , если кому интересно. Для проверки сделал так: на сервере: ACP=1252 (зап. Европа), SQLCOLLATION=1251 (кириллица), DBCOLLATION=1254 (турция) на клиенте: ACP=1255 (Иврит) в БД записана строка (один байт на символ) в турецкой кодировке 1254, моя задача правильно ее получить через SELECT используя ADO. Опытным путем установлено, что сервер при Auto Translate=False отдает все правильно (один байт на символ), а уже на клиенте ADO или сам провайдер (не знаю кто именно) преобразовывает данную строку с клиентским системным ACP (в моем тесте это 1255 иврит) и возвращает в Field.Value юникод строку BSTR. Естественно это будут еврейские каракули. Далее нужно эту юникод строку свернуть обратно в ANSI с системной ACP. На выходе получаем ту самую строку-оригинал один байт на символ, которая и была в таблице. Если ее нужно сконвертить в юникод, то нужно знать кодировку БД (знать заранее или достать через sql-запрос) и уже выполнить преобразование с этой кодировкой в юникод. Вот так. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:06 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно ? вы заблуждаетесь и судя по всему не понимаете, как оно работает в с++\c# коде. Вам кажется, если вы закроете глаза на тип а базе, то LPSTR сделает для вас чудо? хренушки, в приложении это будет указатель на строку. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:12 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
Ролг Хупин victorov1 Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно ? вы заблуждаетесь и судя по всему не понимаете, как оно работает в с++\c# коде. Вам кажется, если вы закроете глаза на тип а базе, то LPSTR сделает для вас чудо? хренушки, в приложении это будет указатель на строку. Мне нужно было или получить оригинал LPSTR (как в БД записан), или BSTR с учетом кодировки самой БД. Я проблему решил и описал выше. А вот почему ADO конверить строки из ANSI в юникод с системной ACP - большой вопрос. МОгли бы сделать в таком случае VT_LPSTR вместо VT_BSTR, если от серера приходит ANSI-строка. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 17:17 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
victorov1 Ролг Хупин пропущено... вы заблуждаетесь и судя по всему не понимаете, как оно работает в с++\c# коде. Вам кажется, если вы закроете глаза на тип а базе, то LPSTR сделает для вас чудо? хренушки, в приложении это будет указатель на строку. Мне нужно было или получить оригинал LPSTR (как в БД записан), или BSTR с учетом кодировки самой БД. Я проблему решил и описал выше. А вот почему ADO конверить строки из ANSI в юникод с системной ACP - большой вопрос. МОгли бы сделать в таком случае VT_LPSTR вместо VT_BSTR, если от серера приходит ANSI-строка. ну, вам написали выше - 1. делайте конверт в запросе 2. сделайте вью 3. То, что вы нашли это не решение в общем-то, это припарки. делайте в юникод (1,2 или добавьте поле) и расслабьтесь ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 18:04 |
|
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
|
|||
---|---|---|---|
#18+
Сейчас ради интереса проверил MySQL ODBC 8.0 Unicode Driver и о чудо! Он работает корректно. Т.е. на запрос SELECT возвращается юникод-строка с учетом кодировки БД и без учета текущей системной ACP клиента! Майкрософты почему-то этого не делают и приходится плясать с бубном. Топик можно закрыть (не вижу как это сделать). Всем спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.03.2021, 18:47 |
|
|
start [/forum/topic.php?fid=46&fpage=31&tid=1684952]: |
0ms |
get settings: |
8ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
52ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
74ms |
get tp. blocked users: |
2ms |
others: | 316ms |
total: | 486ms |
0 / 0 |