将 XML 数据存储在表中的 PL/SQL 过程抛出错误(23,102):PL/SQL:ORA-00907:缺少右括号

Posted

技术标签:

【中文标题】将 XML 数据存储在表中的 PL/SQL 过程抛出错误(23,102):PL/SQL:ORA-00907:缺少右括号【英文标题】:PL/SQL procedure to store XML data in a table throws Error(23,102): PL/SQL: ORA-00907: missing right parenthesis 【发布时间】:2017-08-02 08:54:15 【问题描述】:

我正在编写一个 PL/SQL 过程,我正在读取一个 XML 并将 XML 中的数据存储在一个表中。

输入的XML如下:

<MatAnnounceRcv xmlns="http://adc.wed.com/apps/ij/mes/common/v2017">
    <Header>
        <DATESEND>2017-05-07</DATESEND>
        <TIMESEND>13:11:35</TIMESEND>
    </Header>
    <AnnounceItems>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <MATERIAL_TYPE>BR</MATERIAL_TYPE>
    </AnnounceItems>
    <MatBatchChars>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <ATNAM>GRADE_NAME</ATNAM>
        <ATWRT>186C</ATWRT>
    </MatBatchChars>
    <MatBatchChars>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <ATNAM>BREITE</ATNAM>
        <ATNUM>1912</ATNUM>
        <UNIT>MM</UNIT>
    </MatBatchChars>
    <MatBatchChars>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <ATNAM>WEIGHT</ATNAM>
        <ATNUM>30966</ATNUM>
        <UNIT>KG</UNIT>
    </MatBatchChars>
    <MatBatchChars>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <ATNAM>SLAB_ID</ATNAM>
        <ATWRT>Z4895201</ATWRT>
    </MatBatchChars>
    <MatBatchChars>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <ATNAM>SLAB_LEN_ACT</ATNAM>
        <ATNUM>9205</ATNUM>
        <UNIT>MM</UNIT>
    </MatBatchChars>
    <MatBatchChars>
        <MATERIAL>STEEL</MATERIAL>
        <BATCH>Z4895201</BATCH>
        <ATNAM>SLAB_THK_ACT</ATNAM>
        <ATNUM>255</ATNUM>
        <UNIT>MM</UNIT>
    </MatBatchChars>    
</MatAnnounceRcv>

而建表查询如下:

CREATE TABLE COMMAT 
(   CONTROLID NUMBER NOT NULL , 
    PKEYITEM VARCHAR2(40 CHAR), 
    ME_ID VARCHAR2(20 CHAR) NOT NULL , 
    BEZEICHNUNG VARCHAR2(40 CHAR) NOT NULL , 
    P_STATUS VARCHAR2(2 CHAR) DEFAULT 'PR' NOT NULL , 
    FA_NR VARCHAR2(20 CHAR), 
    AG_ID NUMBER(4,0), 
    TYP VARCHAR2(2 CHAR), 
    KZGESPERRT VARCHAR2(1 CHAR) DEFAULT 'N', 
    SPERRGRUND VARCHAR2(30 CHAR), 
    BEMERKUNG VARCHAR2(80 CHAR), 
    BESTANDSART VARCHAR2(1 CHAR), 
    ANZ_STUECKE NUMBER(4,0) DEFAULT 1, 
    BREITE NUMBER(12,4), 
    DICKE NUMBER(12,4), 
    LAENGE NUMBER(12,4), 
    DIAGONALE NUMBER(12,4), 
    INNENDM NUMBER(12,4), 
    GEW NUMBER(12,4), 
    GEWBRUTTO NUMBER(12,4), 
    LETZTE_BEARB DATE, 
    ORT_PHYS VARCHAR2(40 CHAR), 
    BEREIT_AB DATE, 
    FOLGEANLAGE VARCHAR2(10 CHAR), 
    SP_STATUS VARCHAR2(2 CHAR), 
    VERPACKUNGSSCHLUESSEL VARCHAR2(20 CHAR), 
    PGBEZEICHNUNGIST VARCHAR2(12 CHAR), 
    DTERZEUGT DATE, 
    HEATNO VARCHAR2(20 CHAR), 
    MAT_ST_ID VARCHAR2(40 CHAR), 
    MAT_ST_VERSION NUMBER(4,0), 
    SUB_NR NUMBER(9,0) DEFAULT 0, 
    GRADE VARCHAR2(32 CHAR), 
    QGRADE VARCHAR2(50 CHAR), 
    QSTANDARD VARCHAR2(50 CHAR), 
    PLANMATNO VARCHAR2(32 CHAR), 
    AU_NRIST VARCHAR2(20 CHAR), 
    UPOS_NRIST VARCHAR2(8 CHAR), 
    SCOPE VARCHAR2(40 CHAR) DEFAULT '1/', 
    ERSTELLER VARCHAR2(32 CHAR), 
    ERSTELLDATUM DATE, 
    AENDERER VARCHAR2(32 CHAR), 
    AENDDATUM DATE, 
    ARCHIVDATUM DATE, 
    UPDATEZAEHLER NUMBER(8,0), 
    SYSTEM VARCHAR2(30 CHAR), 
    CONSTRAINT PK_COMMAT PRIMARY KEY (CONTROLID, ME_ID)
);

我写的程序如下:

create or replace 
PROCEDURE ANNOUNCEITEMS_UPLOAD(XMLINPUT IN CLOB) AS 
controlid VARCHAR2(20);
primarykeyitem VARCHAR2(20);
meid VARCHAR2(20);


BEGIN

SELECT TRUNC(dbms_random.VALUE(100000, 999999)) num INTO controlid from dual;
SELECT x.* INTO primarykeyitem,meid FROM xmltable(XMLNAMESPACES('http://adc.wed.com/apps/ij/mes/common/v2017' as "ns"), 
 '/ns:MatAnnounceRcv/ns:AnnounceItems'
 PASSING xmltype(XMLINPUT)

 COLUMNS 

 PKEYITEM VARCHAR2(40) PATH '//ns:BATCH',
 ME_ID VARCHAR2(20) PATH '//ns:BATCH'

  )x;


INSERT INTO COMMAT(CONTROLID,PKEYITEM,ME_ID,ORT_PHYS,BEZEICHNUNG,TYP,BREITE,DICKE,LAENGE,GEW,GRADE) 
SELECT controlid,primarykeyitem,meid,'--',x.* FROM xmltable (
  XMLNAMESPACES('http://adc.wed.com/apps/ij/mes/common/v2017' as "ns"),
 '//ns:MatAnnounceRcv'
 PASSING xmltype(XMLINPUT)

 COLUMNS 

    BEZEICHNUNG VARCHAR2(40) PATH '//ns:MatBatchChars[ns:ATNAM=''SLAB_ID'']/ns:ATWRT',
    TYP VARCHAR2(2) PATH '//ns:AnnounceItems/ns:MATERIAL_TYPE',
    BREITE NUMBER(12,4) PATH '//ns:MatBatchChars[ns:ATNAM=''BREITE'']/ns:ATNUM',
    DICKE NUMBER(12,4) PATH '//ns:MatBatchChars[ns:ATNAM=''SLAB_THK_ACT'']/ns:ATNUM',
    LAENGE NUMBER(12,4) PATH '//ns:MatBatchChars[ns:ATNAM=''SLAB_LEN_ACT'']/ns:ATNUM',
    GEW NUMBER(12,4) PATH '//ns:MatBatchChars[ns:ATNAM=''WEIGHT'']/ns:ATNUM',
    GRADE VARCHAR2(32) PATH '//ns:MatBatchChars[ns:ATNAM=''GRADE_NAME'']/ns:ATWRT'


)x;

END ANNOUNCEITEMS_UPLOAD;

但是编译的时候报错:

Error(23,1): PL/SQL: SQL Statement ignored
Error(24,4): PL/SQL: ORA-00907: missing right parenthesis

我看不到括号不匹配。

【问题讨论】:

【参考方案1】:

Oracle 的错误消息是虚假的——真正的罪魁祸首是 XPath 表达式中的单引号。只需用双引号替换它们,您的程序就可以编译得很好,例如而不是

PATH '//ns:MatBatchChars[ns:ATNAM=''BREITE'']/ns:ATNUM'

使用

PATH '//ns:MatBatchChars[ns:ATNAM="BREITE"]/ns:ATNUM'

【讨论】:

我爱你。从 EXTRACTVALUE 迁移到 XML_TABLE 时,过去 2 个小时一直在试图找出这个愚蠢的错误。

以上是关于将 XML 数据存储在表中的 PL/SQL 过程抛出错误(23,102):PL/SQL:ORA-00907:缺少右括号的主要内容,如果未能解决你的问题,请参考以下文章

如何将 PL/SQL 的输出(XML)存储在 oracle 表中

PL/SQL 仅使用游标将 2 个表中的数据检索到新表中

PL/SQL Developer 中执行过程的问题

如何在 PL/SQL 中增量集成数据

如何修复存储过程 Oracle PL/SQL 的错误?

pl/sql 存储过程从日期等于存储过程参数的表中进行选择