如何将XML数据存储在Oracle中的表中?

问题陈述:

您需要将本机XML数据存储到数据库中的关系表中。

解:

Oracle有几种存储XML文档的方法。在不需要更改XML或可以使用XSLT提取XML的一部分的情况下,一种存储数据的方法是使用XMLTYPE数据转换。

我们将使用XMLTYPE调用将提供的文本转换为XMLTYPE数据类型。在后台,Oracle XMLTYPE支持CLOB数据类型,因为XML在内部存储为CLOB。这意味着我们可以使用相同的方法进行转换,将调用传递给XMLTYPE一个最大4GB的字符串。

强制转换为XMLTYPE对我们的XML数据强制执行一些规则。如果使用XML架构定义了列或表,则该架构将用于验证数据,确保存在强制性元素,并且整个结构准确地映射到该架构。

我们将首先创建一个表来存储XML。

创建表tmp_store_xml(结果XMLTYPE);

DECLARE
  result XMLTYPE;
    data VARCHAR2(10);
BEGIN
      FOR CUR IN (SELECT department_id FROM departments)
      LOOP
          WITH tmp AS
            (SELECT XMLROOT(XMLFOREST( dept_t(department_id, department_name,
                    CAST(MULTISET
                        (SELECT student_id,
                                first_name,
                                last_name,
                                phone_number
                           FROM students e
                          WHERE e.department_id = d.department_id
                        ) AS stulist_t
                        )) AS "Department"),version '1.0') AS dataxml
                FROM departments d
               WHERE d.department_id = '' || cur.department_id || ''
             )
       
        SELECT XMLTYPE.CREATEXML(XMLSERIALIZE(CONTENT (dataxml) INDENT size=2))
               INTO result
          FROM tmp;
         
        INSERT INTO tmp_store_xml VALUES(result);
        COMMIT;
      END LOOP;
END;

输出:表中的一行

<Department DEPTNO="60">
  <DNAME>IT</DNAME>
  <STU_LIST>
    <STU_T STUNO="103">
      <FNAME>BROWN</FNAME>
      <LNAME>MICHAEL</LNAME>
      <PHONE>111.111.1248</PHONE>
    </STU_T>
    <STU_T STUNO="104">
      <FNAME>JONES</FNAME>
      <LNAME>WILLIAM</LNAME>
      <PHONE>111.111.1249</PHONE>
    </STU_T>
    <STU_T STUNO="105">
      <FNAME>MILLER</FNAME>
      <LNAME>DAVID</LNAME>
      <PHONE>111.111.1250</PHONE>
    </STU_T>
    <STU_T STUNO="106">
      <FNAME>DAVIS</FNAME>
      <LNAME>RICHARD</LNAME>
      <PHONE>111.111.1251</PHONE>
    </STU_T>
    <STU_T STUNO="107">
      <FNAME>GARCIA</FNAME>
      <LNAME>CHARLES</LNAME>
      <PHONE>111.111.1252</PHONE>
    </STU_T>
  </STU_LIST>
</Department>

数据准备:用于该问题的数据如下所示。数据完全用于演示目的。

示例

DROP TABLE students;
COMMIT;

CREATE TABLE students
    ( student_id     NUMBER(6)
    , first_name     VARCHAR2(20)
    , last_name      VARCHAR2(25)
    , email          VARCHAR2(40)
    , phone_number   VARCHAR2(20)
    , join_date      DATE
    , class_id       VARCHAR2(20)  
    , fees           NUMBER(8,2)
    , professor_id   NUMBER(6)
    , department_id  NUMBER(4)
    ) ;

示例

CREATE UNIQUE INDEX stu_id_pk ON students (student_id) ;
INSERT INTO students VALUES (100,'SMITH','JAMES','SMITH.JAMES@notreal.com','111.111.1245',TO_DATE('17-06-2003','DD-MM-YYYY'),'INS_CHAIRMAN',24000,NULL,NULL);
INSERT INTO students VALUES (101,'JOHNSON','JOHN','JOHNSON.JOHN@notreal.com','111.111.1246',TO_DATE('21-09-2005','DD-MM-YYYY'),'INS_VP',17000,100,90);
INSERT INTO students VALUES (102,'WILLIAMS','ROBERT','WILLIAMS.ROBERT@notreal.com','111.111.1247',TO_DATE('13-01-2001','DD-MM-YYYY'),'INS_VP',17000,100,90);
INSERT INTO students VALUES (103,'BROWN','MICHAEL','BROWN.MICHAEL@notreal.com','111.111.1248',TO_DATE('03-01-2006','DD-MM-YYYY'),'INS_STAFF',9000,102,60);
INSERT INTO students VALUES (104,'JONES','WILLIAM','JONES.WILLIAM@notreal.com','111.111.1249',TO_DATE('21-05-2007','DD-MM-YYYY'),'INS_STAFF',6000,103,60);
INSERT INTO students VALUES (105,'MILLER','DAVID','MILLER.DAVID@notreal.com','111.111.1250',TO_DATE('25-06-2005','DD-MM-YYYY'),'INS_STAFF',4800,103,60);
INSERT INTO students VALUES (106,'DAVIS','RICHARD','DAVIS.RICHARD@notreal.com','111.111.1251',TO_DATE('05-02-2006','DD-MM-YYYY'),'INS_STAFF',4800,103,60);
INSERT INTO students VALUES (107,'GARCIA','CHARLES','GARCIA.CHARLES@notreal.com','111.111.1252',TO_DATE('07-02-2007','DD-MM-YYYY'),'INS_STAFF',4200,103,60);
INSERT INTO students VALUES (108,'RODRIGUEZ','JOSEPH','RODRIGUEZ.JOSEPH@notreal.com','111.111.1253',TO_DATE('17-08-2002','DD-MM-YYYY'),'CL_PHY',12008,101,100);
INSERT INTO students VALUES (109,'WILSON','THOMAS','WILSON.THOMAS@notreal.com','111.111.1254',TO_DATE('16-08-2002','DD-MM-YYYY'),'CL_MATH',9000,108,100);
INSERT INTO students VALUES (110,'MARTINEZ','CHRISTOPHER','MARTINEZ.CHRISTOPHER@notreal.com','111.111.1255',TO_DATE('28-09-2005','DD-MM-YYYY'),'CL_MATH',8200,108,100);
INSERT INTO students VALUES (111,'ANDERSON','DANIEL','ANDERSON.DANIEL@notreal.com','111.111.1256',TO_DATE('30-09-2005','DD-MM-YYYY'),'CL_MATH',7700,108,100);
INSERT INTO students VALUES (112,'TAYLOR','PAUL','TAYLOR.PAUL@notreal.com','111.111.1257',TO_DATE('07-03-2006','DD-MM-YYYY'),'CL_MATH',7800,108,100);
INSERT INTO students VALUES (113,'THOMAS','MARK','THOMAS.MARK@notreal.com','111.111.1258',TO_DATE('07-12-2007','DD-MM-YYYY'),'CL_MATH',6900,108,100);

COMMIT;

示例

CREATE TABLE departments
    ( department_id    NUMBER(4)
    , department_name  VARCHAR2(30)
    CONSTRAINT  dept_name_nn  NOT NULL
    , professor_id       NUMBER(6)
    , location_id      NUMBER(4)
    ) ;

示例

INSERT INTO departments VALUES ( 10, 'Administration', 200, 1700);
INSERT INTO departments VALUES ( 20, 'Teaching', 201, 1800);                            
INSERT INTO departments VALUES ( 30  , 'Purchasing'  , 114   , 1700 );
INSERT INTO departments VALUES ( 40  , 'Human Resources'  , 203  , 2400  );
INSERT INTO departments VALUES ( 50  , 'Students'  , 121  , 1500  );
INSERT INTO departments VALUES ( 60   , 'IT'  , 103  , 1400  );
INSERT INTO departments VALUES ( 70   , 'Public Relations'  , 204  , 2700  );
INSERT INTO departments VALUES ( 80   , 'Fee collectors'  , 145  , 2500  );  
INSERT INTO departments VALUES ( 90   , 'Executive'  , 100  , 1700  );
INSERT INTO departments VALUES ( 100   , 'Finance'  , 108  , 1700  );  
INSERT INTO departments VALUES ( 110   , 'Accounting'  , 205  , 1700  );
INSERT INTO departments VALUES ( 120   , 'Treasury'  , NULL  , 1700  );
INSERT INTO departments VALUES ( 130   , 'Corporate Tax'  , NULL  , 1700  );
INSERT INTO departments VALUES ( 140   , 'Control And Credit'  , NULL  , 1700  );
INSERT INTO departments VALUES ( 160   , 'Benefits'  , NULL  , 1700  );
INSERT INTO departments VALUES ( 230   , 'Helpdesk'  , NULL  , 1700  );
COMMIT;