0

假设我有一张客户表。 在此处输入图像描述

并且有三列(id [type-Number],name [type-Varchar2],detail [type-XMLTYPE]。详细列包含xml格式的客户地址,包括他的姓名,与第二列名称相同。

在此处输入图像描述

  1. 第一个 sql:工作正常[两列的名称相同]

    SELECT id,
    name,
    extractValue(detail, '/customer/address[@type=''HOME'']/name1') name1
    FROM
    (
        SELECT inner1.*,
        (SELECT detail FROM customer c1 WHERE c1.id = inner1.id) detail
        FROM
        (SELECT c.id, c.name FROM customer c ) inner1
    )
    

    输出 :

    1   Janice  Janice
    2   Rita    Rita
    3   Cory    Cory
    
  2. 第二个 sql [无法正常工作:name1 对于第一行的所有行都是重复的]

    SELECT id,
    name,
    extractValue(detail, '/customer/address[@type=''HOME'']/name1') name1,
    extractValue(detail, '/customer/address[@type=''HOME'']/name2') name2
    FROM
      (
        SELECT inner1.*,
              (SELECT detail FROM customer c1 WHERE c1.id = inner1.id) detail
        FROM
          (SELECT c.id, c.name FROM customer c) inner1
      )
    

    输出 :

    1   Janice  Janice  Dunn
    2   Rita    Janice  Hale
    3   Cory    Janice  Jones
    

问题:在第二个 sql 中,我只从详细列中请求了额外的数据 name2,这完全改变了输出,因为您可以在第二个 sql 的输出中看到 name1 的重复数据。这种行为是如何可能的,可能的解决方案是什么?

如果我不在 sql 的 xpath 中使用属性,则问题不存在。sql 仍然有效并提供正确的数据。 喜欢

extractValue(detail, '/customer/address/name1') name1,

细节

  1. Oracle 数据库 11g 版本 11.2.0.3.0 - 64 位生产
  2. 客户.sql

    创建表“客户”

    (   "ID" NUMBER, 
        "NAME" VARCHAR2(20 BYTE), 
        "DETAIL" "SYS"."XMLTYPE" 
       )
    
     XMLTYPE COLUMN "DETAIL" STORE AS SECUREFILE BINARY XML (
      TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192
      CACHE  NOCOMPRESS  KEEP_DUPLICATES 
      STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
      PCTINCREASE 0
      BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)) ALLOW NONSCHEMA DISALLOW ANYSCHEMA ;   
    
    Insert into CUSTOMER (ID,NAME,DETAIL) values (1,'Janice','<?xml version = ''1.0''?><customer>
       <customerno>1</customerno>
       <address type="HOME">
          <name1>Janice</name1>
          <name2>Dunn</name2>
          <email>janice.dunn98@example.com</email>
          <dob>5/2/1980</dob>
          <city>Barn St</city>
       </address>
    </customer>');
    Insert into CUSTOMER (ID,NAME,DETAIL) values (2,'Rita','<?xml version = ''1.0''?><customer>
       <customerno>2</customerno>
       <address type="HOME">
          <name1>Rita</name1>
          <name2>Hale</name2>
          <email>rita.hale40@example.com</email>
          <dob>2/2/1981</dob>
          <city>Seventh St</city>
       </address>
    </customer>');
    Insert into CUSTOMER (ID,NAME,DETAIL) values (3,'Cory','<?xml version = ''1.0''?><customer>
       <customerno>3</customerno>
       <address type="HOME">
          <name1>Cory</name1>
          <name2>Jones</name2>
          <email>cory.jones89@example.com</email>
          <dob>9/7/1984</dob>
          <city>Arther St</city>
       </address>
    </customer>');
    
4

1 回答 1

0

EXTRACTVALUE(和 EXTRACT)在 11g 中被弃用。相反,您应该使用 10g 中引入的 XMLTABLE 函数,如下所示:

WITH customer AS (SELECT 1 ID, 'Janice' NAME, XMLTYPE('<?xml version="1.0"?>
<customer><customerno>1</customerno>
   <address type="HOME">
      <name1>Janice</name1>
      <name2>Dunn</name2>
      <email>janice.dunn98@example.com</email>
      <dob>5/2/1980</dob>
      <city>Barn St</city>
   </address>
</customer>') detail FROM dual UNION ALL
                  SELECT 2 ID, 'Rita' NAME , XMLTYPE('<?xml version="1.0"?><customer>
   <customerno>2</customerno>
   <address type="HOME">
      <name1>Rita</name1>
      <name2>Hale</name2>
      <email>rita.hale40@example.com</email>
      <dob>2/2/1981</dob>
      <city>Seventh St</city>
   </address>
</customer>') detail FROM dual UNION ALL
                  SELECT 3 ID, 'Cory' NAME , XMLTYPE('<?xml version="1.0"?><customer>
   <customerno>3</customerno>
   <address type="HOME">
      <name1>Cory</name1>
      <name2>Jones</name2>
      <email>cory.jones89@example.com</email>
      <dob>9/7/1984</dob>
      <city>Arther St</city>
   </address>
</customer>') detail FROM dual)
-- end of mimicking your customer table - you would not need the above, as you already have the table.
-- see the SQL below:
SELECT c.id,
       c.name,
       x.name1,
       x.name2
FROM   customer c
       CROSS JOIN XMLTABLE('/customer' PASSING c.detail
                           COLUMNS name1 VARCHAR2(20) PATH 'address[@type="HOME"]/name1',
                                   name2 VARCHAR2(20) PATH 'address[@type="HOME"]/name2') x;

        ID NAME   NAME1                NAME2
---------- ------ -------------------- --------------------
         1 Janice Janice               Dunn
         2 Rita   Rita                 Hale
         3 Cory   Cory                 Jones

至于你的问题。为什么 EXTRACTVALUE 没有给出正确的结果 - 当我使用与我的答案相同的数据运行您的确切 sql 语句时,我得到完全相同的结果。我在 11.2.0.4,我只能得出结论,如果你得到错误的答案,那一定是你的特定版本的 Oracle 中的一个错误。

但是,我很困惑为什么您要执行标量子查询来检索详细信息列-您的 xml 列与实际数据库中的其他详细信息不在同一个表中吗?

于 2017-05-19T14:07:14.673 回答