#sql #teradata
#sql #teradata
Вопрос:
На основе моих исследований до сих пор этот символ указывает на неправильное кодирование между базой данных и интерфейсом. К сожалению, у меня нет никакого контроля ни над одним из них. Я использую Teradata Studio.
Как я могу отфильтровать этот символ? Я пытаюсь выполнить REGEX_SUBSTR
функцию для столбца, который иногда содержит �
, которая выдает ошибку «Строка содержит непереводимый символ».
Вот мой SQL. AIRCFT_POSITN_ID
— это столбец, содержащий символ замены.
SELECT DISTINCT AIRCFT_POSITN_ID,
REGEXP_SUBSTR(AIRCFT_POSITN_ID, '[0-9] ') AS AUTOROW
FROM PROD_MAE_MNTNC_VW.FMR_DISCRPNCY_DFRL
WHERE DFRL_CREATE_TMS > CURRENT_DATE -25
Ответ №1:
Ваша диагностика верна, поэтому, прежде всего, вы можете захотеть проверить набор символов сеанса (это часть определения соединения). Если это ASCII, измените его на UTF8, и вы сможете увидеть исходные символы вместо символа замены.
И в случае, если символ действительно является частью данных, а не просто указанием на проблемы с кодированием переводов:
Символ замены, ОН ЖЕ SUB (шестнадцатеричное значение 26 ДЕКАБРЯ: 1A), совершенно уникален в Teradata.
вы не можете использовать его напрямую —
select '�';
-- [6706] The string contains an untranslatable character.
select '1A'XC;
-- [6706] The string contains an untranslatable character.
Если вы используете версию 14.0 или выше, вы можете сгенерировать его с помощью функции CHR:
select chr(26);
Если у вас ниже версии 14.0, вы можете сгенерировать его следующим образом:
select translate (_unicode '05D0'XC using unicode_to_latin with error);
После того, как вы сгенерировали символ, теперь вы можете использовать его с помощью REPLACE или OTRANSLATE
create multiset table t (i int,txt varchar(100) character set latin) unique primary index (i);
insert into t (i,txt) values (1,translate ('Hello שלום world עולם' using unicode_to_latin with error));
select * from t;
-- Hello ���� world ����
select otranslate (txt,chr(26),'') from t;
-- Hello world
select otranslate (txt,translate (_unicode '05D0'XC using unicode_to_latin with error),'') from t;
-- Hello world
Кстати, существует 2 версии для OTRANSLATE и OREPLACE:
- Функции в syslib работают с ЛАТИНИЦЕЙ.
- функции в TD_SYSFNLIB работают с ЮНИКОДОМ.
Комментарии:
1. Можете ли вы показать рабочий
oTranslate
, для меня это всегда не удавалось. Afaik толькоUdf_checklatin
функция из инструмента Teradata для Юникода может это сделать:Kithttps://downloads.teradata.com/download/tools/unicode-tool-kit2. @dnoeth, я добавил полный пример к своему ответу
3. Это по-прежнему возвращает ошибку 6706 Строка содержит непереводимый символ в 15 и 15.10. В вашей системе, вероятно,
AcceptReplacementCharacters
вinternal
поле dbscontrol включено.4. @masospaghetti отвечает ли это на ваш вопрос? вы нашли причину ошибки?
5. @Dudu Markovitz Я отметил ваш ответ как ответ, потому что он был очень полезным и информативным. В итоге я «решил» эту проблему, заключив запрос в другой оператор SELECT. Teradata автоматически очистила данные, выполнив это, и избавилась от символов замены. OREPLACE И OTRANSLATE не работают в моей версии Teradata.
Ответ №2:
В дополнение к превосходному ответу Дуду выше, я хотел добавить следующее теперь, когда я снова столкнулся с проблемой и у меня было больше времени для экспериментов. Следующая команда SELECT создала непереводимый символ:
SELECT IDENTIFY FROM PROD_MAE_MNTNC_VW.SCHD_MNTNC;
IDENTIFY
24FEB1747659193DC330A163DCL�ORD
Попытка выполнить REGEXP_REPLACE или OREPLACE непосредственно для этого символа приводит к ошибке:
Failed [6706 : HY000] The string contains an untranslatable character.
Я изменил свойство CHARSET в моем соединении с Teradata с UTF8 на ASCII, и теперь я мог видеть символ-нарушитель, похожий на вкладку
IDENTIFY
Использование команды TRANSLATE_CHK с использованием этого конкретного преобразования завершается успешно и определяет позицию символа-нарушителя (обратите внимание, что это не работает с использованием кодировки UTF8):
TRANSLATE_CHK(IDENTIFY USING KANJI1_SBC_TO_UNICODE) AS BADCHAR
BADCHAR
28
Теперь с этим символом можно справиться, используя некоторые операторы CASE, чтобы удалить неверный символ и сохранить оставшуюся часть строки:
CASE WHEN TRANSLATE_CHK(IDENTIFY USING KANJI1_SBC_TO_UNICODE) = 0 THEN IDENTIFY
ELSE SUBSTR(IDENTIFY, 1, TRANSLATE_CHK(IDENTIFY USING KANJI1_SBC_TO_UNICODE)-1)
END AS IDENTIFY
Надеется, что это кому-то поможет.
Комментарии:
1. Большое вам спасибо за команду TRANSLATE_CHK. Это помогло мне идентифицировать одну оскорбительную запись среди 3 миллионов записей.