4

バッチ入力 (つまり、プレーン テキスト) を検証しています。timestamp検証の最初の段階は、タイムスタンプに配置する前に、順序付けする必要がある列が実際に正しい形式であることを確認することです。この場合'yyyy/mm/dd hh24:mi:ss:ff2'

ただし、Oracle は、タイムスタンプ形式の小数秒の精度から先頭の 0 を削除しているように見えます。たとえば、009はそのままでは 2 (またはそれ以下) の精度であると想定されますが、 では0099ありません0090。最初の 2 つの例は、明らかに正しくありません。日付/時刻形式モデルの目的上、秒の小数部の精度が先行する 0 を除く精度であるように見えます。

動作は精度に関係なく発生するようです。

この例は正しいです:

select to_timestamp('2012/06/20 05:12:41:91','yyyy/mm/dd hh24:mi:ss:ff2') t
  from dual;

T
---------------------------------------------------------------------------
20-JUN-12 05.12.41.910000000

これらの例は正しくありません:

エラーが発生することが予想されますが、切り捨てられても対処できます。

select to_timestamp('2012/06/20 05:12:41:091','yyyy/mm/dd hh24:mi:ss:ff2') t
  from dual;

 T
---------------------------------------------------------------------------
20-JUN-12 05.12.41.091000000

select to_timestamp('2012/06/20 05:12:41:0091','yyyy/mm/dd hh24:mi:ss:ff2') t
  from dual;

T
---------------------------------------------------------------------------
20-JUN-12 05.12.41.009100000

select to_timestamp('2012/06/20 05:12:41:00091','yyyy/mm/dd hh24:mi:ss:ff2') t
  from dual;

T
---------------------------------------------------------------------------
20-JUN-12 05.12.41.000910000

このエラーは正しいです。小数秒の精度は 3 です。

select to_timestamp('2012/06/20 05:12:41:901','yyyy/mm/dd hh24:mi:ss:ff2') t
  from dual;
select to_timestamp('2012/06/20 05:12:41:901','yyyy/mm/dd hh24:mi:ss:ff2') t
                    *
ERROR at line 1:
ORA-01880: the fractional seconds must be between 0 and 999999999

私はリリース 11.2.0.1.0 を使用していますが、この動作は 11.1.0.6.0 および 9.2.0.1.0 でも発生するため、明らかにしばらく前から存在しています。

これは私が以前は知らなかった「機能」ですか?

解決策は、すべてのタイムスタンプの精度が 6 桁であると想定しているようですが、与えられたデータが正しいことを実際に検証できる別の方法はありますか?

4

1 に答える 1

1

あなたはすでに計画を立てていると思いますが、私は演劇をすると思いました。to_charで2桁に切り捨てられるようです.ff2-その論理は私には失われています-したがって、提供された値を切り捨てて満足している場合は、それを跳ね返すことができます(醜い、必要ではない方法で) ):

select to_timestamp(
        to_char(
            to_timestamp('2012/06/20 05:12:41:091',
                'yyyy/mm/dd hh24:mi:ss:ff9'),
            'yyyy/mm/dd hh24:mi:ss:ff2'),
        'yyyy/mm/dd hh24:mi:ss:ff2') t
from dual;

T
---------------------------------------------------------------------------
20-JUN-12 05.12.41.090000000

もちろん、それを関数に入れることもできます:

create or replace function my_to_timestamp(p_str varchar2)
return timestamp is
begin
    return to_timestamp(
            to_char(
                to_timestamp(p_str, 'yyyy/mm/dd hh24:mi:ss:ff9'),
                'yyyy/mm/dd hh24:mi:ss:ff2'),
            'yyyy/mm/dd hh24:mi:ss:ff2');
end;
/

select my_to_timestamp('2012/06/20 05:12:41:91') from dual;

MY_TO_TIMESTAMP('2012/06/2005:12:41:91')
---------------------------------------------------------------------------
20-JUN-12 05.12.41.910000000

select my_to_timestamp('2012/06/20 05:12:41:091') from dual;

MY_TO_TIMESTAMP('2012/06/2005:12:41:091')
---------------------------------------------------------------------------
20-JUN-12 05.12.41.090000000

select my_to_timestamp('2012/06/20 05:12:41:901') from dual;

MY_TO_TIMESTAMP('2012/06/2005:12:41:901')
---------------------------------------------------------------------------
20-JUN-12 05.12.41.900000000

または、同じメカニズムを使用してエラーにすることもできます。

create or replace function my_to_timestamp(p_str varchar2)
return timestamp is
    ts timestamp;
begin
    ts := to_timestamp(p_str, 'yyyy/mm/dd hh24:mi:ss:ff9');
    if ts != to_timestamp(
                to_char(
                    to_timestamp(p_str, 'yyyy/mm/dd hh24:mi:ss:ff9'),
                    'yyyy/mm/dd hh24:mi:ss:ff2'),
                'yyyy/mm/dd hh24:mi:ss:ff2')
    then
        raise program_error;
    end if;
    return ts;
end;
/

select my_to_timestamp('2012/06/20 05:12:41:91') from dual;

MY_TO_TIMESTAMP('2012/06/2005:12:41:91')
---------------------------------------------------------------------------
20-JUN-12 05.12.41.910000000

select my_to_timestamp('2012/06/20 05:12:41:091') from dual;

select my_to_timestamp('2012/06/20 05:12:41:091') from dual
       *
ERROR at line 1:
ORA-06501: PL/SQL: program error
ORA-06512: at "SCOTT.MY_TO_TIMESTAMP", line 12

select my_to_timestamp('2012/06/20 05:12:41:901') from dual;

select my_to_timestamp('2012/06/20 05:12:41:901') from dual
       *
ERROR at line 1:
ORA-06501: PL/SQL: program error
ORA-06512: at "SCOTT.MY_TO_TIMESTAMP", line 12

代わりに例外とプラグマを追加して ORA-01880 をスローさせることもできますが、とにかくそのメッセージが完全に役立つかどうかはわかりません。

于 2012-07-10T18:46:16.030 に答える