Экранирование символов для использования с Oracle Xmltable - PullRequest
0 голосов
/ 28 марта 2019

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

WITH

data AS
  (
    select  1 ID, 'foo&bar@domain.tld,bar@domain.tld' recipients from dual
  )

select  ID, trim(COLUMN_VALUE) recipient
from    data,xmltable(('"'|| REPLACE( recipients , ',', '","') || '"'))

выдает ошибку:

[72000] [19112] ORA-19112: ошибка, возникшая при оценке: XVM-01003: [XPST0003] Синтаксическая ошибка в «foo» 1 "foo&bar@domain.tld", "bar@domain.tld" - ^

Однако, когда я заменяю & его значением сущности (&):

WITH

DATA AS
  (
    select  1 ID, 'foo&bar@domain.tld,bar@domain.tld' recipients from dual
  )

select  ID
        -- & --> &
        , replace( trim(COLUMN_VALUE), '&', '&') recipient
from    data
        -- & --> &
        ,xmltable(('"'|| REPLACE( replace( recipients, '&','&')  , ',', '","') || '"'))

запрос работает:

ID,RECIPIENT
1,foo&bar@domain.tld
1,bar@domain.tld

Я предполагаю, что могут быть другие символы, допустимые в адресе электронной почты, но это будет проблематично для Xmltable.

Есть ли лучший способ сделать это?

1 Ответ

2 голосов
/ 28 марта 2019

Вы можете использовать встроенную dbms_xmlgen.convert() функцию :

with data (id, recipients) as
(
  select 1, 'foo&bar@domain.tld,bar@domain.tld' from dual
)
select d.id, dbms_xmlgen.convert(x.column_value.getstringval(), 1) as recipient
from data d
cross join
xmltable(('"' || replace(dbms_xmlgen.convert(d.recipients, 0), ',', '","') || '"')) x

        ID RECIPIENT                     
---------- ------------------------------
         1 foo&bar@domain.tld            
         1 bar@domain.tld                

Внутренний вызов dbms_xmlgen.convert(d.recipients, 0) дает вам

foo&bar@domain.tld,bar@domain.tld

После этогобыли изменены, чтобы иметь двойные кавычки вокруг каждого значения, разделенного запятыми, и были разделены на несколько строк, в результате вы получите column_value как:

foo&bar@domain.tld
bar@domain.tld

, поэтому внешний dbms_xmlgen.convert(x.column_value.getstringval(), 1) преобразует любые закодированные объекты обратно в ихпростые версии.

Если вы делаете это в контексте PL / SQL, тогда вы можете использовать dbms_xmlgen.entity_encode и dbms_xmlgen.entity_decode вместо фиксированных 0 и 1, но они не доступны в простом SQL.

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

...