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

时间:2014-09-27 09:28:26

标签: sql oracle date

我收到错误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。所以这里发生了例外。

2 个答案:

答案 0 :(得分:1)

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

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。然而,虽然这看起来很奇怪,但甲骨文似乎没有问题。

下一个问题是:

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');

但是,再一次,请勿在{{1​​}}值上使用to_date,所以

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'))而不是两位数年份。 2位数年份YYYY将被解释为2014年,14将被解释为2015年,但在2位数年开始被解读为上个世纪之前,您还能走多远?也许15会被解释为1950年?

答案 1 :(得分:0)

只是猜测:

我注意到您在查询中使用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');