转义字符以用于 Oracle 的 Xmltable

Escaping characters for use with Oracle's Xmltable

我正在使用 Xmltable 将逗号分隔的电子邮件地址字段转换为 table 个值。

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: error raised during evaluation: XVM-01003: [XPST0003] Syntax error at '"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 来说会有问题。

有更好的方法吗?

您可以使用 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 需要担心,但您仍然不妨考虑所有这些 - 无论它们在电子邮件地址中是否有效 - 并且使用这样的函数调用可能会减少对未来维护者的混淆...)