【问题标题】:Escaping characters for use with Oracle's Xmltable用于 Oracle 的 Xmltable 的转义字符
【发布时间】:2019-08-19 10:27:31
【问题描述】:

我正在使用 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 会出现问题。

有没有更好的方法来做到这一点?

【问题讨论】:

标签: sql oracle oracle12c xmltable


【解决方案1】:

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

【讨论】:

  • dbms_xmlgen.convert(d.recipients, 0) 工作正常。 dbms_xmlgen.convert(x.column_value.getstringval(), 1) 生成错误42000][904] ORA-00904: "X"."COLUMN_VALUE"."GETSTRINGVAL": invalid identifier
  • @craig - 这与 11.2.0.4 及更高版本中发布的完全相同(包括in 18c);它不起作用in 11.2.0.2,但出于不同的原因。不清楚为什么这很重要,但您使用的是哪个版本? (我刚刚注意到 XMLTable 表达式的 x 别名可能需要水平滚动才能看到 - 我已经将它拆分到一个新行以停止它,以防万一你错过了它...... )
猜你喜欢
  • 2010-11-11
  • 2012-03-08
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2012-09-23
  • 2016-04-28
  • 2015-01-07
  • 2021-09-14
相关资源
最近更新 更多