我有一个XML列,它与下面提到的类似。
<appl>
<sftp_job name = "test1_ftp">
<ftp_job name = "test2_ftp">
<link name="testlink1">
<tag name ="task1_ftp">
<unix_job name="test123_ftp">
</appl>
我的要求是获取以“_ftp”结尾的所有atrributes的值,如下所述。
test1_ftp
test2_ftp
task1_ftp
test123_ftp
我有以下SQL语句,它工作正常。
SELECT JOB_NAME
FROM
(SELECT q.jobname AS JOB_NAME
FROM DFTAB1
LEFT JOIN xmltable('/appl/*[contains(name(),"_job") or
contains(name(),"link") or
contains(name(),"task") ]'
PASSING XMLTYPE(DEF) columns jobname VARCHAR2(20) path '@name')q ON (1=1)
)
WHERE JOB_NAME LIKE '%_ftp%'
这是有效的。
我是否可以在单个SELECT语句中执行此操作。
答案 0 :(得分:2)
您可以在XPath查询中组合布尔运算符:
SELECT x.job_name
FROM DFTAB1 d
CROSS JOIN XMLTable(
'/appl/*[(contains(name(),"_job")
or contains(name(),"link")
or contains(name(),"task"))
and (ends-with(@name, "_ftp"))]'
PASSING XMLTYPE(d.DEF)
COLUMNS job_name VARCHAR2(20) path '@name'
) x;
我使用了交叉连接而不是左外连接,这实际上是一个内部连接,并且由于虚拟条件而实际上是交叉连接。我刚刚将生成的列调用为您希望它最终的结果,因此您不需要别名。
使用示例XML进行演示(带标签关闭)
with DFTAB1 (DEF) as (
select '<appl>
<sftp_job name = "test1_ftp" />
<ftp_job name = "test2_ftp" />
<link name="testlink1" />
<tag name ="task1_ftp" />
<unix_job name="test123_ftp" />
</appl>' from dual
)
SELECT x.job_name
FROM DFTAB1 d
CROSS JOIN XMLTable(
'/appl/*[(contains(name(),"_job")
or contains(name(),"link")
or contains(name(),"task"))
and (ends-with(@name, "_ftp"))]'
PASSING XMLTYPE(d.DEF)
COLUMNS job_name VARCHAR2(20) path '@name'
) x;
JOB_NAME
--------------------
test1_ftp
test2_ftp
test123_ftp
与原始查询获得的结果相同;由于task1_ftp
与原始tag
支票不符,因此未包含contains
。
虽然存在细微的差别,但我认为从问题的措辞来看,这实际上是正确的,而且你的原文并不完整。当你执行LIKE '%_ftp%'
时,下划线也是一个单字符的通配符,因此匹配说abcftp
,这是我认为你不想要的。等效值将被转义为LIKE '%\_ftp%' ESCAPE '\'
。
正如MTO所提到的,一个更重要的变化是,您的查询在作业名称的任何位置查找_ftp
(或者,如上所述,实际上只是ftp
)。您的问题实际上是以“_ftp”结尾,因此您的描述和查询不匹配。如果您确实希望它在属性值中的任何位置,请再次使用contains
而不是ends-with
:
SELECT x.job_name
FROM DFTAB1 d
CROSS JOIN XMLTable(
'/appl/*[(contains(name(),"_job")
or contains(name(),"link")
or contains(name(),"task"))
and (contains(@name, "_ftp"))]'
PASSING XMLTYPE(d.DEF)
COLUMNS job_name VARCHAR2(20) path '@name'
) x;
虽然结果与您的样本相同。
答案 1 :(得分:1)
SELECT q.jobname AS JOB_NAME
FROM DFTAB1 d
CROSS JOIN
XMLTABLE(
'/appl/*[contains(name(),"_job") or
contains(name(),"link") or
contains(name(),"task") ]'
PASSING XMLTYPE(d.DEF)
columns jobname VARCHAR2(20) path '@name'
) q
WHERE q.JOBNAME LIKE '%_ftp%'