繁体   English   中英

可能的日期分配错误ORA-01858:在期望数字的位置找到了非数字字符

[英]Possible Date assignment error ORA-01858: a non-numeric character was found where a numeric was expected

我收到错误ORA-01858:在非预期的数字位置发现了一个非数字字符,我认为这是因为代码中的日期分配不正确。 有人可以看一下下面的代码片段,如果错误的话,可以让我知道分配日期的正确方法吗?

     Declare

        v_task_start DATE;   
        v_task_completion DATE;  
        v_prj_start DATE;
        v_prj_completion DATE;
        l_start_date DATE;
        l_completion_date DATE;
        v_task_id NUMBER;
        v_prj_id  NUMBER;

        CURSOR c_tasks_to_update IS
            SELECT 
            pt.TASK_ID, 
            pt.Project_id AS Task_Prj_Id, 
            pt.start_date  AS Task_start,
            pt.Completion_date AS Task_Completion,
            ppa.start_date AS Project_start,
            ppa.completion_date AS Project_completion
            INTO
            v_task_id, v_prj_id, v_task_start, v_task_completion, v_prj_start, v_prj_completion
            FROM pa_tasks pt, pa_projects_all ppa
            WHERE pt.project_id = ppa.project_id
            AND pt.created_by = 1623
            and to_date(pt.creation_date,'DD-MON-YY') = to_date('26-SEP-2014', 'DD-MON-YY');

     BEGIN



          FOR ctask_update in c_tasks_to_update
          LOOP

              v_task_start          := ctask_update.Task_start;
              v_task_completion     := ctask_update.Task_Completion;
              v_prj_start           := ctask_update.Project_start;
              v_prj_completion      := ctask_update.Project_completion;

              IF ((v_task_start <> v_prj_start) and (v_task_completion <> v_prj_completion))
              THEN
               DBMS_OUTPUT.put_line( 'Task Start date is not equal to Project start date, 
               Task completion date is not equal to Project completion date '
                ||v_task_start||' '||v_prj_start||' '||v_task_completion ||' '||   
                  v_prj_completion);

                l_start_date := to_date(trunc(v_prj_start),'DD_MON_YY');

                /*SELECT START_DATE FROM PA_PROJECTS_ALL
                      INTO l_start_date
                   FROM pa_projects_all WHERE project_id = v_prj_id;*/


                l_completion_date := to_date('trunc(v_prj_completion)','DD_MON_YY');

                /*SELECT completion_date FROM PA_PROJECTS_ALL
                  INTO l_completion_date
                  FROM pa_projects_all WHERE project_id = v_prj_id;*/

                  DBMS_OUTPUT.put_line( 'Task start date to be updated to '||
                    to_char(l_start_date));
                  DBMS_OUTPUT.put_line( 'Task completion date to be updated to '||  
                    to_char(l_completion_date));

    End;

我看不到输出语句“ Task start date to be updated to:xxxx 因此,这里发生了异常。

我在这里可以看到很多问题。 首先,以下行:

and to_date(pt.creation_date,'DD-MON-YY') = to_date('26-SEP-2014', 'DD-MON-YY');

pt.creation_date是什么类型? CHARVARCHAR2DATE

请勿将CHARVARCHAR2列用作日期,否则所有其他垃圾内容都可能会出现在您的日期列中:例如31-SEP-14tomorrown/aasdf ,所有这些都会在以后的发布中引起问题处理。 您的错误可能是由此列中的脏数据引起的。

如果pt.creation_dateDATE ,则无需在其上调用to_date ,因为这将迫使Oracle将日期转换为字符串然后再转换为日期。 这是不必要的。

另外, to_date('26-SEP-2014', 'DD-MON-YY')也不完全正确,因为您在日期字符串中使用四位数的年份2014和在日期格式中使用两位数的年份YY图片。 但是,尽管这看起来很奇怪,但是Oracle似乎没有问题。

下一个问题在这里:

l_start_date := to_date(trunc(v_prj_start),'DD_MON_YY');

v_prj_start已经是DATE ,因此无需将其转换为日期。 您正在进行不必要的从日期到字符串然后再返回的转换。 仅仅写就足够了

l_start_date := trunc(v_prj_start);

另外,我不确定您为什么在日期格式图片( 'DD_MON_YY' )中使用下划线。

我看到的下一个问题是这一行:

l_completion_date := to_date('trunc(v_prj_completion)','DD_MON_YY');

这很可能是产生错误的那一行。 实际上,它会因您报告的错误消息而完全失败。 这是因为字符串'trunc(v_prj_completion)'不是您指定格式的有效日期。 Oracle在日期字符串的开头希望有一个数字,而您给它指定了字母t 我想您打算改为编写以下行:

 l_completion_date := to_date(trunc(v_prj_completion),'DD_MON_YY');

但是,再次,不要在DATE值上使用to_date ,因此

 l_completion_date := trunc(v_prj_completion);

可能就足够了。

接下来的两行类似于以下内容:

DBMS_OUTPUT.put_line( 'Task start date to be updated to '||
                    to_char(l_start_date));

始终将to_char与日期格式的图片一起使用,例如to_char(l_start_date, 'DD-MON-YY')

最后,一般来说,请使用四位数的年份( YYYY ),而不是两位数的年份。 2位数字的年份14将被解释为2014年,而15位将被解释为2015年,但是在2位数字年份开始像上世纪一样被解释之前,您还能走多远? 也许50将被解释为1950?

只是一个疯狂的猜测:

正如我已经注意到的,您在查询中使用TO_DATEpt.creation_date转换为适当的日期值,我可以假设其他日期也可能以字符串形式存储在表中(这是一个不好的主意 )。

所以我会尝试这样的事情:

v_task_start          := TO_DATE(ctask_update.Task_start,'DD-MON-YY');
v_task_completion     := TO_DATE(ctask_update.Task_Completion,'DD-MON-YY');
v_prj_start           := TO_DATE(ctask_update.Project_start,'DD-MON-YY');
v_prj_completion      := TO_DATE(ctask_update.Project_completion,'DD-MON-YY');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM