Поиск и удаление не ascii символов из Oracle Varchar2 - PullRequest
24 голосов
/ 10 февраля 2010

В настоящее время мы переносим одну из наших баз данных Oracle в UTF8, и мы нашли несколько записей, которые близки к пределу 4000 байтов varchar. Когда мы пытаемся перенести эти записи, они терпят неудачу, так как содержат символы, которые становятся многобайтовыми символами UF8. В PL / SQL я хочу найти эти символы, чтобы увидеть, какие они есть, а затем либо изменить их, либо удалить их.

Я бы хотел сделать:

SELECT REGEXP_REPLACE(COLUMN,'[^[:ascii:]],'')

но Oracle не реализует класс символов [: ascii:].

Есть ли простой способ делать то, что я хочу?

Ответы [ 16 ]

22 голосов
/ 30 июля 2011

Если вы используете функцию ASCIISTR для преобразования Юникода в литералы вида \nnnn, вы можете затем использовать REGEXP_REPLACE для удаления этих литералов, например ...

UPDATE table SET field = REGEXP_REPLACE(ASCIISTR(field), '\\[[:xdigit:]]{4}', '')

... где field и table - ваши имена полей и таблиц соответственно.

21 голосов
/ 19 ноября 2015

Я думаю, что это поможет

SELECT REGEXP_REPLACE(COLUMN, '[^[:print:]]', '')
9 голосов
/ 14 августа 2013

Я бы не рекомендовал его для производственного кода, но он имеет смысл и, кажется, работает:

SELECT REGEXP_REPLACE(COLUMN,'[^' || CHR(1) || '-' || CHR(127) || '],'')
7 голосов
/ 10 февраля 2010

В однобайтовой ASCII-совместимой кодировке (например, Latin-1) символы ASCII - это просто байты в диапазоне от 0 до 127. Таким образом, вы можете использовать что-то вроде [\x80-\xFF] для обнаружения не-ASCII символов.

4 голосов
/ 10 сентября 2010

Выбор может выглядеть следующим образом:

select nvalue from table
where length(asciistr(nvalue))!=length(nvalue)  
order by nvalue;
3 голосов
/ 19 января 2012

Работает также следующее:

select dump(a,1016), a from (
SELECT REGEXP_REPLACE (
          CONVERT (
             '3735844533120%$03  ',
             'US7ASCII',
             'WE8ISO8859P1'),
          '[^!@/\.,;:<>#$%&()_=[:alnum:][:blank:]]') a
  FROM DUAL);
3 голосов
/ 10 февраля 2010

Возможно, есть более прямой способ использования регулярных выражений. Если повезет, кто-то еще предоставит это. Но вот что я бы сделал, не обращаясь к руководствам.

Создайте функцию PLSQL для получения вашей входной строки и возврата varchar2.

В функции PLSQL выполните asciistr () вашего ввода. PLSQL вызван тем, что может возвращать строку длиннее 4000, и у вас есть 32K для varchar2 в PLSQL

Эта функция преобразует не-ASCII-символы в нотацию \ xxxx. Таким образом, вы можете использовать регулярные выражения, чтобы найти и удалить их. Затем верните результат.

2 голосов
/ 24 апреля 2012

Попробуйте следующее:

-- To detect
select 1 from dual
where regexp_like(trim('xx test text æ¸¬è© ¦ “xmx” number²'),'['||chr(128)||'-'||chr(255)||']','in')

-- To strip out
select regexp_replace(trim('xx test text æ¸¬è© ¦ “xmxmx” number²'),'['||chr(128)||'-'||chr(255)||']','',1,0,'in')
from dual
2 голосов
/ 10 августа 2011

Я нашел ответ здесь:

http://www.squaredba.com/remove-non-ascii-characters-from-a-column-255.html

CREATE OR REPLACE FUNCTION O1DW.RECTIFY_NON_ASCII(INPUT_STR IN VARCHAR2)
RETURN VARCHAR2
IS
str VARCHAR2(2000);
act number :=0;
cnt number :=0;
askey number :=0;
OUTPUT_STR VARCHAR2(2000);
begin
str:=’^'||TO_CHAR(INPUT_STR)||’^';
cnt:=length(str);
for i in 1 .. cnt loop
askey :=0;
select ascii(substr(str,i,1)) into askey
from dual;
if askey < 32 or askey >=127 then
str :=’^'||REPLACE(str, CHR(askey),”);
end if;
end loop;
OUTPUT_STR := trim(ltrim(rtrim(trim(str),’^'),’^'));
RETURN (OUTPUT_STR);
end;
/

Затем запустите это, чтобы обновить ваши данные

update o1dw.rate_ipselect_p_20110505
set NCANI = RECTIFY_NON_ASCII(NCANI);
2 голосов
/ 11 февраля 2010

У меня была похожая проблема, и я написал об этом в блоге здесь . Я начал с регулярного выражения для буквенных чисел, а затем добавил несколько основных знаков препинания, которые мне понравились:

select dump(a,1016), a, b
from
 (select regexp_replace(COLUMN,'[[:alnum:]/''%()> -.:=;[]','') a,
         COLUMN b
  from TABLE)
where a is not null
order by a;

Я использовал dump с вариантом 1016, чтобы выдавать шестнадцатеричные символы, которые я хотел заменить, и которые я затем мог использовать в utl_raw.cast_to_varchar2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...