Oracle引发ORA-01722:与嵌套xmltable合并时的无效数字

时间:2017-01-24 11:20:23

标签: oracle merge xmltable

我正在运行应解析xml的代码并将其添加到我的表中。 XML代码从变量“s”加载。我的xml样本是:

<?xml version="1.0" encoding="utf-8"?><response>
 <item>
  <id>7294478</id>
  <type>ad</type>
  <stats list="true">
   <period>
    <day>2012-12-26</day>
    <spent>132.00</spent>
    <impressions>93315</impressions>
    <clicks>4</clicks>
    <reach>38039</reach>
   </period>
   <period>
    <day>2012-12-27</day>
    <impressions>7237</impressions>
    <reach>4332</reach>
   </period>
   <period>
    <day>2012-12-28</day>
    <impressions>571</impressions>
    <reach>452</reach>
   </period>
  </stats>
 </item>
</response>

这是我试图运行的代码的一部分:

MERGE INTO VK_AD_STATS r
                USING (SELECT hmn.STATS_ID,                   
                            hmn.STATS_type,     
                            items.STATS_day,      
                            items.STATS_spent,             
                            items.STATS_impressions,   
                            items.STATS_clicks,
                            items.STATS_reach, 
                            items.STATS_video_views, 
                            items.STATS_video_views_half,  
                            items.STATS_video_views_full,            
                            items.STATS_video_clicks_site,          
                            items.STATS_join_rate
                FROM XMLTABLE('response/item' passing (SELECT xmltype(s)  resp FROM dual)
                       COLUMNS    STATS_ID NUMBER                   path '/item/id', 
                                  STATS_type VARCHAR2(2000)         path '/item/type',
                                  STATS_XML xmltype                 path '/item/stats/period'
                                  )hmn ,
                      XMLTABLE('period' passing hmn.STATS_XML
                       COLUMNS      STATS_day VARCHAR2(2000) path '/period/day',      
                                    STATS_spent NUMBER path '/period/spent',             
                                    STATS_impressions NUMBER path '/period/impressions',   
                                    STATS_clicks NUMBER path '/period/clicks',
                                    STATS_reach NUMBER path '/period/reach', 
                                    STATS_video_views NUMBER path '/period/video_views', 
                                    STATS_video_views_half NUMBER path '/period/video_views_half',  
                                    STATS_video_views_full NUMBER path '/period/video_views_full',            
                                    STATS_video_clicks_site NUMBER path '/period/_video_clicks_site ',          
                                    STATS_join_rate NUMBER path '/period/join_rate'
                                  ) items) proc
              ON (r.STATS_ID = proc.STATS_ID and r.STATS_day = proc.STATS_day)
              WHEN MATCHED THEN UPDATE SET r.STATS_type = proc.STATS_type,
                                            r.STATS_spent = proc.STATS_spent,
                                            r.STATS_impressions = proc.STATS_impressions,
                                            r.STATS_clicks = proc.STATS_clicks,
                                            r.STATS_reach = proc.STATS_reach,
                                            r.STATS_video_views = proc.STATS_video_views,
                                            r.STATS_video_views_half = proc.STATS_video_views_half,
                                            r.STATS_video_views_full = proc.STATS_video_views_full,
                                            r.STATS_video_clicks_site = proc.STATS_video_clicks_site,
                                            r.STATS_join_rate = proc.STATS_join_rate
              WHEN NOT MATCHED THEN INSERT (r.STATS_ID,
                                                  r.STATS_type,
                                                  r.STATS_day,
                                                  r.STATS_spent,
                                                  r.STATS_impressions,
                                                  r.STATS_clicks,
                                                  r.STATS_reach,
                                                  r.STATS_video_views,
                                                  r.STATS_video_views_half,
                                                  r.STATS_video_views_full,
                                                  r.STATS_video_clicks_site,
                                                  r.STATS_join_rate
                                                 )
                                      VALUES (proc.STATS_ID,
                                                  proc.STATS_type,
                                                  proc.STATS_day,
                                                  proc.STATS_spent,
                                                  proc.STATS_impressions,
                                                  proc.STATS_clicks,
                                                  proc.STATS_reach,
                                                  proc.STATS_video_views,
                                                  proc.STATS_video_views_half,
                                                  proc.STATS_video_views_full,
                                                  proc.STATS_video_clicks_site,
                                                  proc.STATS_join_rate
                                      );
              COMMIT;     

但它引发了ORA-01722:无效数字

2 个答案:

答案 0 :(得分:2)

将已用完的列提取为文本,然后将其转换为指定NLS_NUMERIC_CHARCTERS以用作小数分隔符:

SELECT hmn.STATS_ID,             
       hmn.STATS_type,
       items.STATS_day,
       TO_NUMBER(
         items.STATS_spent,
         '99999999999999999999D99',
         'NLS_NUMERIC_CHARACTERS='',.'''
       ) AS stats_spent,
       items.STATS_impressions,
       items.STATS_clicks,
       items.STATS_reach,
       items.STATS_video_views,
       items.STATS_video_views_half,
       items.STATS_video_views_full,
       items.STATS_video_clicks_site,
       items.STATS_join_rate
FROM   XMLTABLE(
         '/response/item'
         PASSING XMLTYPE(s)
         COLUMNS STATS_ID NUMBER           path '/item/id',
                 STATS_type VARCHAR2(2000) path '/item/type',
                 STATS_XML xmltype         path '/item/stats/period'
       ) hmn,
       XMLTABLE(
         '/period'
         PASSING hmn.STATS_XML
         COLUMNS STATS_day               VARCHAR2(2000) path '/period/day',
                 STATS_spent             VARCHAR2(23)   path '/period/spent',
                 STATS_impressions       NUMBER path '/period/impressions',
                 STATS_clicks            NUMBER path '/period/clicks',
                 STATS_reach             NUMBER path '/period/reach',
                 STATS_video_views       NUMBER path '/period/video_views',
                 STATS_video_views_half  NUMBER path '/period/video_views_half',
                 STATS_video_views_full  NUMBER path '/period/video_views_full',
                 STATS_video_clicks_site NUMBER path '/period/_video_clicks_site',
                 STATS_join_rate         NUMBER path '/period/join_rate'
               ) items

答案 1 :(得分:1)

你的问题根本不是XML相关的 - 这个:

<spent>132.00</spent>
如果您的NLS设置使用,作为小数分隔符,则

不会解析为数字。

将您的NLS设置更改为使用.作为小数点分隔符,例如通过运行此PL / SQL块:

begin
  DBMS_SESSION.SET_NLS ('NLS_LANGUAGE' ,'AMERICAN'); 
  DBMS_SESSION.SET_NLS ('NLS_TERRITORY','AMERICA'); 
end;

并且您的代码应该可以使用。