Удаление символа замены � из столбца

#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-kit

2. @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 миллионов записей.