Замена нескольких символов в столбце электронных писем в Oracle

Итак, в основном у меня есть столбец с несколькими электронными письмами, и некоторые из них недействительны и содержат разные символы/возвраты каретки, которые не разрешены.

Ниже показано, как я нахожу недопустимые электронные письма в операторе выбора, но я понятия не имею, как заменить их по отдельности, например, если найден возврат каретки, я знаю, что буду использовать оператор замены. То же самое с любыми специальными символами. Но для этого потребуется написать отдельный запрос для каждого возможного случая?

В основном то, что я прошу, - это наиболее эффективный способ перебора моей таблицы, заменяющий любые символы в адресе электронной почты, который соответствует одному из этих операторов case.

select /*+  parallel(a,12) full(a) */  a.row_id, a.par_row_id, a.attrib_01,     a.created_by, a.last_upd_by from s_contact_xm a 
where a.type = 'Email' and (a.attrib_01 IS NULL
or a.attrib_01 like '% %'
or a.attrib_01 like '%@%@%'
or a.attrib_01 like '%..%'
or a.attrib_01 like '%;%'
or a.attrib_01 like '%:%'
or attrib_01 not like '%@%'
or a.attrib_01 like '%/%'
or a.attrib_01 like '%\%'
or a.attrib_01 like '%|%'
or a.attrib_01 like '%@.%'
or a.attrib_01 like '%@'
or a.attrib_01 like '%.'
or a.attrib_01 like '%(%'
or a.attrib_01 like '%)%'
or a.attrib_01 like '%<%'
or a.attrib_01 like '%>%'
or a.attrib_01 like '%#%'
or a.attrib_01 like '%"%'
or a.attrib_01 like '%.@%'
or a.attrib_01 like '%..%'
or a.attrib_01 like '.%'
or a.attrib_01 IS NULL
or INSTR(a.attrib_01, CHR(13)) > '0'
or INSTR(a.attrib_01, CHR(10)) > '0') and a.created_by = ‘1-XAAX5P’

person BasicHorizon    schedule 14.08.2012    source источник


Ответы (2)


Дело в том, что у вас есть несколько разных категорий потенциальных ошибок. Некоторые опечатки можно исправить; некоторые неисправимые опечатки; а некоторые просто не правы. Теперь можно ли придумать какие-нибудь пуленепробиваемые правила для определения категории любой данной ошибки?

Возможно.

Например, вы можете преобразовать каждое вхождение «%..%» в «%.%». Точно так же вы можете заменить возврат каретки на ноль. Это исправимые опечатки.

Но если кто-то включил " в адрес электронной почты, вы не можете быть уверены, что он действительно хотел ввести: вы предполагаете, что они набрали 2 и не заметили, что они также нажали [shift], или вы замените его на ноль (т.е. удалите Это)? Это не исправимая опечатка (но вы можете решить, что догадки достаточно).

Если адрес электронной почты не содержит @, это недействительный адрес электронной почты, и исправить его невозможно.

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

translate(attrib_01, '()"'||chr(13), '902')

Вам понадобится несколько проходов для преобразования многосимвольных строк, например.

replace(attrib_01, '..', '.')  

Затем вы, вероятно, захотите обрезать начальные или конечные точки

trim(both '.' from attrib_01 ) 

Наконец, вам нужно будет сообщить обо всех тех адресах, которые вы не можете исправить, например о значениях без штруделей (или с несколькими).

Вы можете сократить некоторые из этих правил до меньшего количества шагов, используя REGEXP_REPLACE. Регулярные выражения станут чрезвычайно сложными. Будет проще исправить ситуацию, используя старые функции замены Oracle skool. Я предлагаю вам использовать регулярное выражение только в том случае, если вам действительно нужна производительность. Даже в этом случае вам все равно придется сделать более одного прохода по данным.


"'()"' означает ли это нули и круглые скобки? "

Документация Oracle является исчерпывающей, бесплатной и доступной в Интернете. Вы можете прочитать все о REPLACE(). ПЕРЕВОД() и TRIM().

Но я объясню вызов REPLACE() немного подробнее. Эта функция заменяет каждый символ в первой строке соответствующим символом во второй строке. Любые символы, которым не хватает соответствия, отбрасываются. Следовательно, ( заменяется на 9, ) заменяется на 0, а " заменяется на 2. (посмотрите на QWERTY-клавиатуру, чтобы понять почему). chr(13) (возврат каретки) не имеет соответствия и поэтому отбрасывается (или заменяется на NULL, если вы предпочитаете так думать).


Размышляя об этом, вы могли бы развернуть оператор CASE в предложении set UPDATE, чтобы применять различные вызовы REPLACE(), TRIM() и TRANSLATE() за одно выполнение. Это зависит от того, насколько непроницаемым вы хотите, чтобы ваш код был :)

person APC    schedule 14.08.2012
comment
translate(attrib_01, '()'||chr(13), '902') В этой строке это замена () и нули и возврат каретки? и что означает "902"? Извините за все эти основные вопросы, я просто не очень хорошо разбираюсь в оракуле. '()' означает ли это нули и скобки? - person BasicHorizon; 15.08.2012
comment
UPDATE table SET ATTRIB_01 = translate(attrib_01, '()"'||chr(13), '902'); Update table SET Attrib_01 = replace(attrib_01, '..', '.') ; Update table SET Attrib_01 = trim(both '.' from attrib_01) ; Это то, что вы имеете в виду под несколькими запусками? и я предполагаю, что «902» удаляет возврат каретки? - person BasicHorizon; 15.08.2012

Там вы найдете много ссылок на проверку электронных писем, это не предназначено для решения копирования/вставки или охвата всех случаев для электронных писем, просто показывает подход.

Я бы использовал regexp_replace, ища все, что НЕ является буквенно-цифровым или в списке дополнительных допустимых символов (например, @ или .)

Измените это для своих правил. Он показывает очистку строки от странных или непечатаемых символов:

select regexp_replace('A^b\c@de' || chr(9) || 'f.com', '[^[:alnum:]@.]','') from dual;

[email protected]

В заявлении об обновлении:

update my_table
set email = regexp_replace(email, '[^[:alnum:]@.]','');

ПОЛНЫЙ пример (11gr2):

SQL> create table t1
(
email varchar2(100)
)
Table created.
SQL> insert into t1 values ('a^bc@#.com')
1 row created.
SQL> insert into t1 values ('a\*bc' || chr(10) || '.net')
1 row created.
SQL> commit
Commit complete.
SQL> select * from t1

EMAIL                                                                          
--------------------------------------------------------------------------------
a^bc@#.com                                                                     
a\*bc                                                                          
.net                                                                           


2 rows selected.

SQL> update t1 set email = regexp_replace(email, '[^[:alnum:]@.]','')
2 rows updated.

SQL> commit
Commit complete.
SQL> select * from t1

EMAIL                                                                           
--------------------------------------------------------------------------------
[email protected]                                                                       
abc.net                                                                         

2 rows selected.

Обратите внимание, что это не применяет никаких строгих правил электронной почты, оно просто удаляет символы за пределами допустимого диапазона символов (о чем спрашивал ваш OP).

person tbone    schedule 14.08.2012
comment
Спасибо, кажется, это то, что я ищу, просто теперь нужно изучить регулярное выражение и как изменить то, что вы написали, чтобы оно мне подходило :) Я знаю, что это не было частью моего первоначального вопроса, но не могли бы вы объяснить [^[ :alnum:]@.] часть мне? - person BasicHorizon; 14.08.2012
comment
Это часть, которая ищет символы, которые НЕ являются буквенно-цифровыми (alnum), символом «@» или символом «.». Alnum — это класс POSIX, используемый для удобства. О регулярных выражениях написано много, но см. docs.oracle.com/ cd/E11882_01/appdev.112/e25518/adfns_regexp.htm - person tbone; 14.08.2012
comment
Я только что попытался запустить этот оператор UPDATE table SET attrib_01 = regexp_replace(attrib_01, '[^[:alnum:]@.]',''); и в нем говорится, что REGEXP_replace является недопустимым именем столбца? - person BasicHorizon; 15.08.2012
comment
@ user1598156 у меня отлично работает, я обновлю свой ответ полным примером. - person tbone; 15.08.2012