【问题标题】:Error when selecting timestamp from XMLType column in Oracle 11g从 Oracle 11g 中的 XMLType 列中选择时间戳时出错
【发布时间】:2015-08-12 07:33:32
【问题描述】:

我有 2 个 Oracle 11g 数据库,其中一个表包含一个 XMLType 列和一些测试数据,仅在时间戳的毫秒内的分隔符 (.,) 中有所不同:

create table TEST_TIMESTAMP (
  ID  number(19,0) constraint "NN_TEST_TIMESTAMP_ID" not null,
  DOC xmltype      constraint "NN_TEST_TIMESTAMP_DOC" not null
);

insert into TEST_TIMESTAMP values ( 1, xmltype('<?xml version="1.0" encoding="utf-8"?><test><ts>2015-04-08T04:55:33.11</ts></test>'));
insert into TEST_TIMESTAMP values ( 2, xmltype('<?xml version="1.0" encoding="utf-8"?><test><ts>2015-04-08T04:55:33,11</ts></test>'));

当我尝试使用以下语句提取时间戳时,一个数据库上的第一个文档或另一个数据库上的第二个文档都会失败。

select x.*
from TEST_TIMESTAMP t,
     xmltable( 
     '/test'
     passing t.DOC
     columns
       ORIGINAL varchar2(50) path 'ts',
       RESULT timestamp with time zone path 'ts'
 ) x
 where t.ID = 1;

 select x.*
 from TEST_TIMESTAMP t,
 xmltable( 
      '/test'
      passing t.DOC
      columns
        ORIGINAL varchar2(50) path 'ts',
        RESULT timestamp with time zone path 'ts'
 ) x
 where t.ID = 2;

我得到的错误:

ORA-01858: a non-numeric character was found where a numeric was expected
01858. 00000 - "a non-numeric character was found where a numeric was expected"
*Cause: The input data to be converted using a date format model was
        incorrect.  The input data did not contain a number where a number was
        required by the format model.
*Action:   Fix the input data or the date format model to make sure the
           elements match in number and type.  Then retry the operation.

我发现的这些数据库之间的唯一区别是:

  • DB1:版本=11.2.0.1.0,NLS_CHARACTERSET=AL32UTF8 -> 在文档 2 上失败
  • DB2:版本=11.2.0.2.0,NLS_CHARACTERSET=WE8MSWIN1252 -> 在文档 1 上失败

DB1 具有我所期望的行为。有谁知道为什么这些数据库的行为不同以及如何解决 DB2 中的问题?

提前致谢, 奥利弗

【问题讨论】:

    标签: oracle oracle11g timestamp xmltype timestamp-with-timezone


    【解决方案1】:

    我的猜测是这两个数据库的 nls_timestamp_format 是不同的。

    但是,我不会在 XMLTABLE 级别强制进行隐式转换,而是在选择列表中进行显式转换:

    with test_timestamp as (select 1 id, xmltype('<?xml version="1.0" encoding="utf-8"?><test><ts>2015-04-08T04:55:33.11</ts></test>') doc from dual union all
                            select 2 id, xmltype('<?xml version="1.0" encoding="utf-8"?><test><ts>2015-04-08T04:55:33,11</ts></test>') doc from dual)
    select x.original,
           to_timestamp(x.original, 'yyyy-mm-dd"T"hh24:mi:ss,ff2') result
    from   test_timestamp t,
           xmltable('/test' passing t.doc
                    columns original varchar2(50) path 'ts') x;
    
    ORIGINAL                                           RESULT                                            
    -------------------------------------------------- --------------------------------------------------
    2015-04-08T04:55:33.11                             08/04/2015 04:55:33.110000000
    2015-04-08T04:55:33,11                             08/04/2015 04:55:33.110000000
    

    注意我发现使用“ss.ff2”会出错,但“ss,ff2”处理这两种情况都很好。不过,我不确定这是否依赖于其他 nls 设置。

    【讨论】:

    • 时间戳和日期格式 NLS_TIME_FORMAT、NLS_TIMESTAMP_FORMAT、NLS_TIME_TZ_FORMAT、NLS_TIMESTAMP_TZ_FORMAT 在两个数据库上是相同的。
    • 我曾希望使用隐式转换,因为这些 XML 文档来自外部源并且时间戳格式可能不同,因此显式转换对我来说无法可靠地工作。我想,最终我会将这种转换移回应用程序层并使用 Java 和 JodaTime。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 2021-08-02
    • 2016-02-16
    • 2019-07-07
    相关资源
    最近更新 更多