在 PL-SQL 存储过程中为 XML 中的每个段生成唯一 ID

Posted

技术标签:

【中文标题】在 PL-SQL 存储过程中为 XML 中的每个段生成唯一 ID【英文标题】:Unique ID generation in PL-SQL stored procedure for each segment in XML 【发布时间】:2017-09-14 09:22:52 【问题描述】:

我编写了一个存储过程来将数据从 xml 存储到表中。以下是 DDL

CREATE TABLE STUDENT (                              
    CONTROL_ID NUMBER(*,0), 
    BATCHS VARCHAR2(255), 
    FNAME VARCHAR2(255), 
    ROLL VARCHAR2(255), 
    CITY VARCHAR2(255), 
    CONSTRAINT PK_STUDENT PRIMARY KEY (CONTROL_ID, BATCHS)
);

CREATE TABLE MARKS_CHAR (   
    CONTROL_ID NUMBER(*,0), 
    BATCHS VARCHAR2(255), 
    SUBJECT VARCHAR2(255), 
    MARK_NUMBER NUMBER(*,0), 
    MARK_GRADE VARCHAR2(255), 
    UNIT VARCHAR2(255), 
    FOREIGN KEY (CONTROL_ID, BATCHS) REFERENCES STUDENT (CONTROL_ID, BATCHS)
);

CREATE SEQUENCE  SEQ_STUDENT  MINVALUE 1000 MAXVALUE 9999999999999999999999999999 INCREMENT BY 3 START WITH 1000 CACHE 10 NOORDER  NOCYCLE  NOPARTITION ;

&以下分别是程序和示例xml

create or replace PROCEDURE STUDENT_MARKS_UPLOAD(XMLINPUT IN CLOB) AS 

controlid INT;

BEGIN


SELECT SEQ_STUDENT.NEXTVAL INTO controlid FROM DUAL;



INSERT INTO STUDENT(CONTROL_ID,BATCHS,FNAME,ROLL,CITY) 
SELECT controlid,x.* FROM xmltable (
  XMLNAMESPACES('http://some.clg.india/statelevel' as "ns"),
 '//ns:student'
 PASSING xmltype(XMLINPUT)

 COLUMNS

    BATCHS VARCHAR2(255) PATH '//ns:header/ns:batch',
    FNAME VARCHAR2(255) PATH '//ns:header/ns:name',
    ROLL VARCHAR2(255) PATH '//ns:header/ns:roll',
    CITY VARCHAR2(255) PATH '//ns:header/ns:city'

)x;


INSERT INTO MARKS_CHAR(CONTROL_ID,UNIT,BATCHS,SUBJECT,MARK_GRADE) 
SELECT controlid,'string',x.* FROM xmltable (
  XMLNAMESPACES('http://some.clg.india/statelevel' as "ns"),
 '//ns:marks[ns:subject/text()!=''Humanities'' and ns:subject/text()!=''Values and Ethics'' and ((string-length(ns:gwrt/text())>0) and (string-length(ns:mnum/text())=0))]'
 PASSING xmltype(XMLINPUT)

 COLUMNS 

    BATCHS VARCHAR2(255) PATH './parent::*/ns:header/ns:batch',
    SUBJECT VARCHAR2(255) PATH '//ns:subject',
    MARK_GRADE VARCHAR2(2000) PATH '//ns:gwrt'

)x;


INSERT INTO MARKS_CHAR(CONTROL_ID,UNIT,BATCHS,SUBJECT,MARK_NUMBER) 
SELECT controlid,'number',x.* FROM xmltable (
  XMLNAMESPACES('http://some.clg.india/statelevel' as "ns"),
 '//ns:marks[ns:subject/text()!=''Humanities'' and ns:subject/text()!=''Values and Ethics'' and ((string-length(ns:mnum/text())>0) and (string-length(ns:gwrt/text())=0))]'
 PASSING xmltype(XMLINPUT)

 COLUMNS 

    BATCHS VARCHAR2(255) PATH './parent::*/ns:header/ns:batch',
    SUBJECT VARCHAR2(255) PATH '//ns:subject',
    MARK_NUMBER INT PATH '//ns:mnum'

)x;


END ANNOUNCEITEMS_UPLOAD;

<class xmlns="http://some.clg.india/statelevel">
    <student>
        <header>
            <name>Topesh</name>
            <roll>0002</roll>
            <batch>A001</batch>
            <address>WB, India</address>
            <city>Kolkata</city>
        </header>
        <marks>
            <subject>Math</subject>
            <mnum>85</mnum>
        </marks>
        <marks>
            <subject>Language</subject>
            <gwrt>A</gwrt>
        </marks>
        <marks>
            <subject>Humanities</subject>
            <mnum>89</mnum>
        </marks>
        <marks>
            <subject>Geo</subject>
            <gwrt>O</gwrt>
        </marks>
        <marks>
            <subject>History</subject>
            <gwrt>A+</gwrt>
        </marks>
        <marks>
            <subject>Physics</subject>
            <mnum>90</mnum>
        </marks>
        <marks>
            <subject>Chemistry</subject>
            <gwrt>B+</gwrt>
        </marks>
        <marks>
            <subject>Values and Ethics</subject>
            <mnum>93</mnum>
        </marks>
    </student>
    <student>
        <header>
            <name>Subham</name>
            <roll>0003</roll>
            <batch>B002</batch>
            <address>UP, India</address>
            <city>Kanpur</city>
        </header>
        <marks>
            <subject>Math</subject>
            <mnum>98</mnum>
        </marks>
        <marks>
            <subject>Language</subject>
            <gwrt>C+</gwrt>
        </marks>
        <marks>
            <subject>Humanities</subject>
            <mnum>67</mnum>
        </marks>
        <marks>
            <subject>Geo</subject>
            <gwrt>E</gwrt>
        </marks>
        <marks>
            <subject>History</subject>
            <gwrt>A</gwrt>
        </marks>
        <marks>
            <subject>Physics</subject>
            <mnum>97</mnum>
        </marks>
        <marks>
            <subject>Chemistry</subject>
            <gwrt>O</gwrt>
        </marks>
        <marks>
            <subject>Values and Ethics</subject>
            <mnum>58</mnum>
        </marks>
    </student>
    <student>
        <header>
            <name>Vinay</name>
            <roll>0001</roll>
            <batch>C003</batch>
            <address>Kerakla, India</address>
            <city>Bangalore</city>
        </header>
        <marks>
            <subject>Math</subject>
            <mnum>99</mnum>
        </marks>
        <marks>
            <subject>Language</subject>
            <gwrt>B</gwrt>
        </marks>
        <marks>
            <subject>Humanities</subject>
            <mnum>81</mnum>
        </marks>
        <marks>
            <subject>Geo</subject>
            <gwrt>E</gwrt>
        </marks>
        <marks>
            <subject>History</subject>
            <gwrt>E</gwrt>
        </marks>
        <marks>
            <subject>Physics</subject>
            <mnum>92</mnum>
        </marks>
        <marks>
            <subject>Chemistry</subject>
            <gwrt>E</gwrt>
        </marks>
        <marks>
            <subject>Values and Ethics</subject>
            <mnum>87</mnum>
        </marks>
    </student>
</class>

输出如下:

对于表 STUDENT

CONTROL_ID  BATCHS  FNAME   ROLL    CITY
1000        A001    Topesh  0002    Kolkata
1000        B002    Subham  0003    Kanpur
1000        C003    Vinay   0001    Bangalore

对于表MARKS_CHAR

CONTROL_ID  BATCHS  SUBJECT MARK_NUMBER MARK_GRADE  UNIT
1000        A001    Language                   A    string
1000        A001    Geo                        O    string
1000        A001    History                    A+   string
1000        A001    Chemistry                  B+   string
1000        B002    Language                   C+   string
1000        B002    Geo                        E    string
1000        B002    History                    A    string
1000        B002    Chemistry                  O    string
1000        C003    Language                   B    string
1000        C003    Geo                        E    string
1000        C003    History                    E    string
1000        C003    Chemistry                  E    string
1000        A001    Math           85               number
1000        A001    Physics        90               number
1000        B002    Math           98               number
1000        B002    Physics        97               number
1000        C003    Math           99               number
1000        C003    Physics        92               number

但要求是对于每个student 段,应该有一个唯一的CONTROL_ID,即,所需的输出将是

CONTROL_ID  BATCHS  FNAME   ROLL    CITY
1000        A001    Topesh  0002    Kolkata
1003        B002    Subham  0003    Kanpur
1006        C003    Vinay   0001    Bangalore

CONTROL_ID  BATCHS  SUBJECT MARK_NUMBER MARK_GRADE  UNIT
1000        A001    Language                   A    string
1000        A001    Geo                        O    string
1000        A001    History                    A+   string
1000        A001    Chemistry                  B+   string
1003        B002    Language                   C+   string
1003        B002    Geo                        E    string
1003        B002    History                    A    string
1003        B002    Chemistry                  O    string
1006        C003    Language                   B    string
1006        C003    Geo                        E    string
1006        C003    History                    E    string
1006        C003    Chemistry                  E    string
1000        A001    Math           85               number
1000        A001    Physics        90               number
1003        B002    Math           98               number
1003        B002    Physics        97               number
1006        C003    Math           99               number
1006        C003    Physics        92               number

请帮助如何在不更改任何架构的情况下在程序中实现这一点。 我正在使用 SQLDeveloper

【问题讨论】:

【参考方案1】:

您创建了序列,但在 INSERT 操作后没有增加它。如果您使用的是 Oracle 11 或更早版本的创建触发器。否则使用自增列。

How to create id with AUTO_INCREMENT on Oracle?

【讨论】:

以上是关于在 PL-SQL 存储过程中为 XML 中的每个段生成唯一 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何在存储过程中使用游标?

PL-SQL 包的创建和应用

获取几个月的最新记录并使用 Oracle PL-SQL 为每个 ID 汇总其值

如何在pl-sql中解析xml?

如何使用 PL-SQL 查询包含 XML 的 Clob 节点

如何使用 PL-SQL 在 Oracle 中获取列数据类型