转义字符以与Oracle的Xmltable一起使用

时间:2019-03-28 15:18:36

标签: sql oracle oracle12c xmltable

我正在使用... IF(A1 >= 50, "10%", "NOT APPLICABLE") ...将用逗号分隔的电子邮件地址字段转换为值表。

Xmltable

产生错误:

  

[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, trim(COLUMN_VALUE) recipient from data,xmltable(('"'|| REPLACE( recipients , ',', '","') || '"')) 替换为其实体值(&)时:

&

查询有效:

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 来说是有问题的。

有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

您可以使用the built-in dbms_xmlgen.convert() function

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_encodedbms_xmlgen.entity_decode来代替固定的0和1,但在普通SQL中不可用。

(反正有only five entities值得担心,但是您仍然可以允许所有这些内容-无论它们在电子邮件地址中是否有效-像这样使用函数调用的次数可能会减少令未来的维护者感到困惑...)