pl sql过程中的日期格式传入字符串

时间:2016-06-21 20:54:18

标签: oracle plsql oracle12c

我无法将正确的日期格式传递给我的程序。我在论坛上搜索但没有找到解决方案。当我在字符串中提取值时,我得到以下结果

select *
  from (select a.col1,
               a.col2,
               a.col3,
               dense_rank() over(order by a.col2) as TheRank,
               round((count(*) over(order by a.col2)), 1) as UniqueRank
          from abt_t a
         where a.col4 >= to_date(05 - JAN - 98, 'YYYY-MM-DD')
           and a.col4 <= 05 - JAN - 98
           and (a.col2 <= '15:59' and a.col2 >= '09:30')
         order by 1 asc, 2)
 where TheRank = 390
   and UniqueRank = 05 - JAN - 98

值05 - JAN - 98与我发起的p_start_dt date:= to_date('1998-01-05', 'YYYY-MM-DD');

非常不同

我试过了

这是我的程序:

create or replace procedure GET_VOL_OPTION_test is

BEGIN
  DECLARE
  -- Local variables here
w_sqlcode                           number := 0;
w_sqlerrm                            char(500) := '';
query_str VARCHAR2(2000);
TYPE cur_typ IS  ref CURSOR;
V_TABLE varchar2(200) :=NULL; 
c cur_typ;
inv_num NUMBER;
exp_dt date;
Curr_dt date;
inv_amt varchar2(5);
p_start_dt date:= to_date('1998-01-05', 'YYYY-MM-DD');
CURSOR CUR_OVRDDEF_PARAM_EN IS
select tname from OPT_TBL_NM_2015_T  order by tname;

BEGIN

  FOR XX IN CUR_OVRDDEF_PARAM_EN LOOP
    BEGIN
      ----


 query_str := 'select * from (select a.col1, a.col2, a.col3,' ||
              'dense_rank() over (order by a.col2) as TheRank,' ||
              'round((count(*) over (order by a.col2)),1) as UniqueRank ' ||
              /*'from '|| p_stock  || ' a' ||*/
              'from abc_t a' ||
              ' where a.col4 >=  to_date(' || to_char(p_start_dt)  || ', ''YYYY-MM-DD'')' || ' and ' || 'a.col4 <= ' || p_start_dt ||
              ' and (a.col2 <= ''15:59'' and a.col2 >= ''09:30'')' ||
              'order by 1 asc,2)' ||
              'where TheRank = 390 and UniqueRank = ' || p_start_dt;    
    OPEN c FOR query_str ;
    LOOP
        FETCH c INTO inv_num, exp_dt, curr_dt, inv_amt;

        EXIT WHEN c%NOTFOUND;
        -- process row here

    END LOOP;

   /*  EXCEPTION
         WHEN OTHERS THEN NULL;
       END;*/

      EXCEPTION
          WHEN OTHERS THEN 
            w_sqlcode := SQLCODE;
            w_sqlerrm := SQLERRM;
        END;
    END LOOP;

    COMMIT;
  END;
  END;

我正在使用oracle 12.如果您需要更多信息,请不要犹豫。

此致

基督教

2 个答案:

答案 0 :(得分:1)

问题是您在没有格式掩码的情况下调用to_char(p_start_dt)(或者稍后在日期使用字符串连接),Oracle将使用NLS_DATE_FORMAT会话参数将日期转换为字符串。如您所见,这可能设置为DD-MON-YY并导致您出现问题。如果要将日期转换为字符串并将其嵌入到动态SQL中,则需要指定转换的格式掩码(即TO_CHAR( p_start_date, 'YYYY-MM-DD' ));但是,更好的解决方案是:

在动态SQL中使用绑定变量,然后在打开游标时传递日期:

DECLARE
  -- Local variables here
  w_sqlcode  number := 0;
  w_sqlerrm  char(500) := '';
  query_str  VARCHAR2(2000)
               := 'select * from (select a.col1, a.col2, a.col3,' ||
                  'dense_rank() over (order by a.col2) as TheRank,' ||
                  'count(*) over (order by a.col2) as UniqueRank' ||
                  ' from abc_t a' ||
                  ' where a.col4 BETWEEN :start_dt AND :start_dt' ||
                  ' and (a.col2 <= ''15:59'' and a.col2 >= ''09:30'')' ||
                  'order by 1 asc,2)' ||
                  'where TheRank = 390 and UniqueRank = :start_dt';
  c          SYS_REFCURSOR;
  inv_num    NUMBER;
  exp_dt     DATE;
  Curr_dt    DATE;
  inv_amt    VARCHAR2(5);
  p_start_dt DATE := DATE '1998-01-05';
  CURSOR CUR_OVRDDEF_PARAM_EN IS
    select tname from OPT_TBL_NM_2015_T  order by tname;
BEGIN
  FOR XX IN CUR_OVRDDEF_PARAM_EN LOOP
    BEGIN
      OPEN c FOR query_str USING p_start_dt;
      LOOP
        FETCH c INTO inv_num, exp_dt, curr_dt, inv_amt;

        EXIT WHEN c%NOTFOUND;
        -- process row here
      END LOOP;
    EXCEPTION
      WHEN OTHERS THEN 
        w_sqlcode := SQLCODE;
        w_sqlerrm := SQLERRM;
    END;
  END LOOP;
  COMMIT;
END;
/

另外,为什么要将UniqueRank与日期值进行比较?

答案 1 :(得分:0)

这是您创建日期比较的行:

' where a.col4 >=  to_date(' || to_char(p_start_dt)  || ', ''YYYY-MM-DD'')' || ' and ' || 'a.col4 <= ' || p_start_dt ||

你得到了

where a.col4 >= to_date(05 - JAN - 98, 'YYYY-MM-DD') and a.col4 <= 05 - JAN - 98

很明显,您的标准日期格式为“DD - MON - RR&#39;”。为什么你甚至依赖于环境?您应该在to_char中指定格式,例如:

to_char(p_start_dt, 'YYYY-MM-DD') 

而不是使用to_char(p_start_dt)p_start_dt(两者都相同;使用默认设置转换为字符串的日期)。

你也缺少引号。正确的语法是:

' where a.col4 >= to_date(''' || to_char(p_start_dt, 'YYYY-MM-DD')  || ''', ''YYYY-MM-DD'') and ' ||
       'a.col4 <= to_date(''' || to_char(p_start_dt, 'YYYY-MM-DD')  || ''', ''YYYY-MM-DD'')' ||

或更简单的ISO日期文字:

' where a.col4 >= date ''' || to_char(p_start_dt, 'YYYY-MM-DD') || ''' and ' ||
       'a.col4 <= date ''' || to_char(p_start_dt, 'YYYY-MM-DD') || '''' ||

当然与

相同
' where a.col4 = date ''' || to_char(p_start_dt, 'YYYY-MM-DD') || '''' ||