Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在Oracle中按名称验证一周中的某一天_Sql_Oracle_Nls Lang - Fatal编程技术网

Sql 在Oracle中按名称验证一周中的某一天

Sql 在Oracle中按名称验证一周中的某一天,sql,oracle,nls-lang,Sql,Oracle,Nls Lang,给定一周中某一天的字符串表示(即星期一、Mardi、ال㶏㶏㶏㶏㶏㶏等)和NLS㶏U日期㶏语言,是否有任何方法验证一周中的这一天是否有效 你问为什么这么难?好吧,如果这只是英语,那么显而易见的事情是这样的: if <day_variable> in ('Monday','Tuesday', ...) then ... 这是一个有趣的错误。。。Oracle建议: 从日期规范中删除“星期几”值,或为儒略日期输入正确的星期几 删除一周中的某一天并不是一个真正的选择,因为这是我唯一感

给定一周中某一天的字符串表示(即星期一、Mardi、ال㶏㶏㶏㶏㶏㶏等)和NLS㶏U日期㶏语言,是否有任何方法验证一周中的这一天是否有效

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

if <day_variable> in ('Monday','Tuesday', ...) then
   ...
这是一个有趣的错误。。。Oracle建议:

从日期规范中删除“星期几”值,或为儒略日期输入正确的星期几

删除一周中的某一天并不是一个真正的选择,因为这是我唯一感兴趣的,而且我的朱利安约会没有一周中的某一天不正确,因为我没有朱利安约会

确认并使用替代日期格式(
Dy
Dy
FMDy
等)显然会导致相同的错误

似乎Oracle内部将所有日期都表示为朱利安日期,并且在这种情况下会感到困惑。


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

据我所知,每次修补数据库(当然不记得这么做)以生成所有可能的日期时,我都要运行以下类似的操作

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
然后,我必须创建一个非确定性的函数,以验证字符串是否(in)正确:


请注意,如果测试的字符串有效,则包含星期几的任何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
     ;

简单的回答是:你不能用甲骨文做到这一点

您可以使用第二天的循环编写PL/SQL函数,如下所示:

create or replace function is_valid_dayname(
  vi_dayname varchar2, 
  vi_nls_date_language varchar2) return integer 
as
  -- Oracle day name constants for NEXT_DAY
  type type_daynames is varray(7) of varchar2(100);
  v_daynames type_daynames := type_daynames('SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY');
  -- date variable for the INTO clause
  v_date date;
begin
  for i in 1 .. 7 loop
    begin 
      select to_date(vi_dayname || to_char(next_day(sysdate, v_daynames(i)), 'yyyymmdd', 'NLS_DATE_LANGUAGE=''' || vi_nls_date_language || ''''), 'day yyyymmdd') into v_date from dual;
      return 1; -- success
    exception when others then null;
    end;
  end loop;
  return 0; -- failure
end;
并使用它:

select is_valid_dayname('invalid dayname', 'GERMAN') from dual;
0

一,

一,

一,

0


哦,“Sonnabend”在德语中是“Samstag”的同义词,但Oracle不知道这一点。因此,我们接近一个解决方案,但它并不完整。

p.S.我自己回答了这个问题,但这并不意味着这是最好的答案。我正在寻找更好的解决方案(即内置的,仅在SQL中)如果可能的话。什么是每周的天数??这是您根据第一个查询创建的视图吗?这是一个伟大而简单的解决方案。如我的答案所示,这将在德语“Sonnabend”上失败,但仍然是一个伟大的解决方案。我将自由编辑您的答案,并根据您的查询添加一个替代方案,因此,请单独的回答是不合理的。问题在于,无法保证一周中的一个语言日不完全包含在另一个语言日内。例如,印度尼西亚语日文和乌兹别克语日文是斯瓦希里语日文的子串。@Thorsten的编辑解决了这一问题,但仍然是一个可怕的问题:-(@Ben此子字符串问题由我的第二个版本处理(除非
是有效工作日名称的一部分,否则不会发生).Wrt to your edit:您分析并测试了您的语句了吗?我无法仅使用
FMDAY
说明符通过sql plus使我的版本工作,子查询的联合可能会失去性能。@Ben一定错过了什么,您的版本基本上可以工作。我没有编辑它……但7行子查询根本不会影响性能我不认为把<代码> SONABAPEN/COD>作为有效的日子是个好主意。工作日是由ISO 8601(和其他的规范机构)定义的,在这一天的第六天是“SAMSTAG”,没有别的。WnnFrd:他们在瑞士使用“SunnabEdand”吗?在德国(至少在我居住的地方),Sonnabend和Samstag都被认为是有效的,没有一个比另一个更好(尽管Sonnabend似乎过时了)。一个人进入“Sonnabend”而被要求输入一个有效的日期名称在这里会很奇怪。要求用户知道ISO名称也会很奇怪。但是,这里可能不涉及用户输入,那么是的,我们可以将其限制为ISO名称。在瑞士,我们称之为“Samschtig”(或者更糟糕的是,周二称之为“Zischtig:-)
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
     ;
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;
create or replace function is_valid_dayname(
  vi_dayname varchar2, 
  vi_nls_date_language varchar2) return integer 
as
  -- Oracle day name constants for NEXT_DAY
  type type_daynames is varray(7) of varchar2(100);
  v_daynames type_daynames := type_daynames('SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY');
  -- date variable for the INTO clause
  v_date date;
begin
  for i in 1 .. 7 loop
    begin 
      select to_date(vi_dayname || to_char(next_day(sysdate, v_daynames(i)), 'yyyymmdd', 'NLS_DATE_LANGUAGE=''' || vi_nls_date_language || ''''), 'day yyyymmdd') into v_date from dual;
      return 1; -- success
    exception when others then null;
    end;
  end loop;
  return 0; -- failure
end;
select is_valid_dayname('invalid dayname', 'GERMAN') from dual;
select is_valid_dayname('samstag', 'GERMAN') from dual;
select is_valid_dayname('SAMSTAG', 'GERMAN') from dual;
select is_valid_dayname('Samstag', 'GERMAN') from dual;
select is_valid_dayname('Sonnabend', 'GERMAN') from dual;