在Oracle

时间:2015-05-05 08:33:21

标签: sql oracle nls-lang

给出一周中某一天的字符串表示(即星期一 Mardi الثلاثاء等),并且有一个NLS_DATE_LANGUAGE 验证的方式,这周的这一天是有效的吗?

为什么你这么难?好吧,如果这只是英语,那么显而易见的事情就像下面这样:

if <day_variable> in ('Monday','Tuesday', ...) then
   ...

我正在尝试这样做,可扩展地,对于几个国家,并且我不知道(并且不能打扰)写出所有当前和未来NLS_DATE_LANGUAGE的所有日子这不是真是一个选择。

下一个选项是一个明确的TO_DATE(),它与星期五很好地合作 - 我怀疑这是巧合'因为它是5月,但在本周其余时间失败了:< / p>

SQL> select to_date('Friday', 'Day') as d from dual;

D
----------
2015-05-01

SQL> select to_date('Monday', 'Day') as d from dual;
select to_date('Monday', 'Day') as d from dual
               *
ERROR at line 1:
ORA-01835: day of week conflicts with Julian date

这是一个有趣的错误...... Oracle建议:

  

从日期规范中删除星期几值或输入Julian日期的正确星期几。

删除一周中的某一天并不是一个真正的选择,因为我对此感兴趣,而且我的Julian日期没有错误的一周,因为我没有Julian日期。

Workaround's suggested elsewhere确认并使用其他日期格式(DydyFMDy等)显然会导致相同的错误。

出现,好像Oracle在内部将所有日期表示为Julian日期,并且在这种情况下感到困惑。

如何在Oracle中验证命名日是否正确?

2 个答案:

答案 0 :(得分:2)

据我所知,每当我们修补数据库(当然不记得这样做)时,我都会遇到类似下面这样的事情,以产生所有可能的日子

select value as language
     , to_char(sysdate + l, 'FMDay', 'nls_date_language=''' || value || '') as name_of_day
  from v$nls_valid_values
 cross join ( select level as l from dual connect by level <= 7 )
 where parameter = 'LANGUAGE'
   and isdeprecated = 'FALSE'
 order by language

执行此操作根本不可扩展,就像我需要一周中的某一天(即1,2,3等),值为based on the current NLS_TERRITORY,这意味着没有可能的一致性。< / p>

to_char(sysdate + l, 'D', 'nls_date_language=''' || value || '') as day_of_week

然后我必须创建一个非确定性的:-(,用于验证字符串是否正确的函数:

create or replace function is_day_of_week (
    PDay in varchar2
  , PDate_Language
    ) return number is

   l_ct number;

begin

   select count(*) into l_ct
     from days_of_the_week
    where name_of_day = PDay
      and language = PDate_Language;

   return l_ct;

end is_day_of_week;

答案 1 :(得分:2)

观察包含星期几的任何7个连续日历日期的字符串表示,如果测试的字符串有效,则必须将测试的星期几字符串作为子字符串。

因此,为了绕过错误,连接以sysdate开头的一周的字符串表示,并根据结果测试你的字符串:

SELECT CASE INSTR(
               to_char ( sysdate + 0, 'Day, DD.MM.YYYY' )   
            || to_char ( sysdate + 1, 'Day, DD.MM.YYYY' )
            || to_char ( sysdate + 2, 'Day, DD.MM.YYYY' )
            || to_char ( sysdate + 3, 'Day, DD.MM.YYYY' )
            || to_char ( sysdate + 4, 'Day, DD.MM.YYYY' )
            || to_char ( sysdate + 5, 'Day, DD.MM.YYYY' )
            || to_char ( sysdate + 6, 'Day, DD.MM.YYYY' )
          , '<the_string_to_test>' )
         WHEN 0 THEN 'invalid'
         ELSE        'valid'
       END  isvalid
  FROM DUAL
     ;

作为一种改进,如果格式字符串和测试字符串可以防止误报,其中测试字符串是有效日期名称的子字符串,那么一天中的分隔符会分开。

SELECT CASE INSTR(
               to_char ( sysdate + 0, '.FMDay., DD.MM.YYYY' )   
            || to_char ( sysdate + 1, '.FMDay., DD.MM.YYYY' )
            || to_char ( sysdate + 2, '.FMDay., DD.MM.YYYY' )
            || to_char ( sysdate + 3, '.FMDay., DD.MM.YYYY' )
            || to_char ( sysdate + 4, '.FMDay., DD.MM.YYYY' )
            || to_char ( sysdate + 5, '.FMDay., DD.MM.YYYY' )
            || to_char ( sysdate + 6, '.FMDay., DD.MM.YYYY' )
          , '.' || '<the_string_to_test>' || '.')
         WHEN 0 THEN 'invalid'
         ELSE        'valid'
       END  isvalid
  FROM DUAL
     ;

<强> 编辑/注

在后一个例子中注意......

  • 并非所有分隔符都有效(使用.测试[作品]和| [失败])
  • 必须使用
  • FMDay作为格式说明符来修剪星期几名称中的尾随空格

编辑#2

这里(几乎)不需要字符串操作:

select 
  case when upper(:day_name) in 
  (
    select to_char(sysdate + 0, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual union all
    select to_char(sysdate + 1, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual union all
    select to_char(sysdate + 2, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual union all
    select to_char(sysdate + 3, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual union all
    select to_char(sysdate + 4, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual union all
    select to_char(sysdate + 5, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual union all
    select to_char(sysdate + 6, 'FMDAY', 'NLS_DATE_LANGUAGE=''' || :nls_date_lang || '''') from dual
  ) then 'valid' else 'invalid'
  end  isvalid
from dual;