powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
25 сообщений из 29, страница 1 из 2
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053518
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подскажите пожалуйста с казалось бы простым вопросом.
У меня есть БД с 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 рабоать правильно в данном случае?
Спасибо.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053537
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1,

TEXT - это не юникодный тип, нужен NTEXT (а лучше NVARCHAR(max))



Попробуйте сконвертировать к юникодному типу в самом запросе

Код: sql
1.
select v = cast(v as nvarchar(max) from table
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053543
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я прекрасно понимаю, что TEXT-не юникод, но ADO возвращает все данные Field.Value в unicode BSTR и почему-то делает это неправильно. Хотя sqlcmd при тех же условиях и тех же запросах делает все верно!
У меня тысячи запросов и я не могу везде ставить cast() - это неправильно.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053547
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
У меня тысячи запросов и я не могу везде ставить cast() - это неправильно.

Вы попробовали и это помогает?
Можно же вашу таблицу во вью обернуть.

А в ADO нельзя явно указать тип поля?
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053558
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLex
victorov1
У меня тысячи запросов и я не могу везде ставить cast() - это неправильно.

Вы попробовали и это помогает?
Можно же вашу таблицу во вью обернуть.

А в ADO нельзя явно указать тип поля?


Да, это помогает конечно, также как и работа с NTEXT, NVARCHAR, но это не тот путь, которым нужно идти. Таблиц много и я должен корректно обрабатывать запросы типа SELECT * FROM даже если там не-юникод строки.
Вопрос в том - почему ADO возвращает Unicode BSTR неправильно сконвертированный в юникод из кодировки БД?
И как sqlcmd это делает корректно?
Про указания типа поля ADO ничего не нашел.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053564
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
Вопрос в том - почему ADO возвращает Unicode BSTR неправильно сконвертированный в юникод из кодировки БД?
И как sqlcmd это делает корректно?
Про указания типа поля ADO ничего не нашел.


Думаю, эффективнее будет спросить на форуме по конкретной платформе разработки (Delphi, .Net или что там у вас).
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053570
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
Т.е. провайдер взял и передал все в кодировке 1254 однобайтными символами, а затем эти байты преобразовал это в Unicode используя 1251! Бред полнейший. 1.Хотя должен по логике просто преобразовать в Unicode, используя 1254.
2.Как заставить ADO рабоать правильно в данном случае?


1. Ваша логика - не совсем правильная. Ежели вы напряжете мозг - поймте почему.

2. Хотите Юникод - преобразуйте в юникод.

select cast(v as NTEXT) as v from [есть таблица TABLE];
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053578
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно?
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053580
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно?

Хотите "как есть" - преобразуйте к binary.

select cast(v as varbinary(max)) as v from [есть таблица TABLE];
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053582
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
только не меняя SQL-запрос!
SELECT * FROM anytable
я хочу чтобы если тип строки adChar, adLongVarChar, adVarChar, я бы получал в Field.Value вариант с типом VT_LPSTR
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053583
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
только не меняя SQL-запрос!
SELECT * FROM anytable
я хочу чтобы если тип строки adChar, adLongVarChar, adVarChar, я бы получал в Field.Value вариант с типом VT_LPSTR

Хотеть никто не запрещает.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053588
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
утилиты sqlcmd, osql корректно отображают данные при таком запросе
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053598
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
утилиты sqlcmd, osql корректно отображают данные при таком запросе

И?
Ты могешь профайлером осмотреть чудесный запрос, который sqlcmd выполняет на сервере.

ЗЫ. Сревер телепатии не обучен.

select v from aTable;

возвращает, например, три байта

1, 2, 3

откуда ADO должно понять, что это турецкие символы?
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053658
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
но это не тот путь, которым нужно идти.

На "не тот путь" ты свернул ещё когда поставил турецкую базу на сервер с русским ANSI. всё остальное - следствия.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053662
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053686
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у как выглядит у вас строка соединения для ADO? какой вы провайдер используете?
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053689
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуйте ODBC драйвер, там есть настройка языка
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053704
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
пробовал три првайдера - Native Client, SQL ODBC Driver For SQL Server и старый OLEDB.1 - результат одинаковый.
Настройки языка там крутил - но они только для текста ошибок
Судя по описанию должно работать Auto Translate=False, но вот как-то не так работает...
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053719
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
пробовал три првайдера - Native Client, SQL ODBC Driver For SQL Server и старый OLEDB.1 - результат одинаковый.
Настройки языка там крутил - но они только для текста ошибок
Судя по описанию должно работать Auto Translate=False, но вот как-то не так работает...


С какого "описания" вы это взяли?
Что "Auto Translate=true" - должно перевести с турецкого на олбанский?

Еще раз:
1, 2, 3 никак не идентифицируются "как турецкие".
Про collation знает только сервер.
Либо вы конвертируете ascii в юникод на сервере, который знает, что это турецкий.
Либо получаете байты на клиенте и САМИ конвертируете в турецкий юникод.
Либо никак.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053729
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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, символы национального алфавита могут быть переведены неправильно.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053730
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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-запрос) и уже выполнить преобразование с этой кодировкой в юникод.
Вот так.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053736
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно ?


вы заблуждаетесь и судя по всему не понимаете, как оно работает в с++\c# коде.
Вам кажется, если вы закроете глаза на тип а базе, то LPSTR сделает для вас чудо? хренушки, в приложении это будет указатель на строку.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053739
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ролг Хупин
victorov1
Окей, ставлю вопрос по-другому: я не хочу юникод, как в этом случае заставить ADO возвратить не BSTR (который юникод), а просто LPSTR, с которым бы я сам уже делал все что угодно ?


вы заблуждаетесь и судя по всему не понимаете, как оно работает в с++\c# коде.
Вам кажется, если вы закроете глаза на тип а базе, то LPSTR сделает для вас чудо? хренушки, в приложении это будет указатель на строку.


Мне нужно было или получить оригинал LPSTR (как в БД записан), или BSTR с учетом кодировки самой БД. Я проблему решил и описал выше. А вот почему ADO конверить строки из ANSI в юникод с системной ACP - большой вопрос. МОгли бы сделать в таком случае VT_LPSTR вместо VT_BSTR, если от серера приходит ANSI-строка.
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053763
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
victorov1
Ролг Хупин
пропущено...


вы заблуждаетесь и судя по всему не понимаете, как оно работает в с++\c# коде.
Вам кажется, если вы закроете глаза на тип а базе, то LPSTR сделает для вас чудо? хренушки, в приложении это будет указатель на строку.


Мне нужно было или получить оригинал LPSTR (как в БД записан), или BSTR с учетом кодировки самой БД. Я проблему решил и описал выше. А вот почему ADO конверить строки из ANSI в юникод с системной ACP - большой вопрос. МОгли бы сделать в таком случае VT_LPSTR вместо VT_BSTR, если от серера приходит ANSI-строка.


ну, вам написали выше -
1. делайте конверт в запросе
2. сделайте вью
3. То, что вы нашли это не решение в общем-то, это припарки. делайте в юникод (1,2 или добавьте поле) и расслабьтесь
...
Рейтинг: 0 / 0
некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
    #40053777
victorov1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сейчас ради интереса проверил MySQL ODBC 8.0 Unicode Driver и о чудо! Он работает корректно. Т.е. на запрос SELECT возвращается юникод-строка с учетом кодировки БД и без учета текущей системной ACP клиента! Майкрософты почему-то этого не делают и приходится плясать с бубном.
Топик можно закрыть (не вижу как это сделать).
Всем спасибо.
...
Рейтинг: 0 / 0
25 сообщений из 29, страница 1 из 2
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / некорректное преобразование ANSI->Unicode (ADO, Auto Translate=False)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]