Oracle 日期错误 - ORA-01841
Oracle Date Error - ORA-01841
我在 Oracle11g 中有以下 table。
SQL> DESC tmp_test;
Name Type Nullable Default Comments
-------------------- ------------- -------- ------- --------
SERNO NUMBER(10)
CARDNO VARCHAR2(25) Y
COL_A VARCHAR2(255) Y
DATEA DATE Y
DATEB DATE Y
TAG VARCHAR2(255) Y
FEEDBACK CHAR(1) Y
SQL>
SQL> SELECT * FROM (SELECT T.COL_A FROM TEMP_TEST T ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <=10;
COL_A
--------------------------------------------------------------------------------
00 OK.20150301-0000
00 OK.20150301-0000
00 OK.20150301-0000
00 OK.20150205-0000
00 OK.20150301-0000
00 OK.20150301-0000
00 OK.20150213-0000
00 OK.20150301-0000
00 OK.20150129-0000
00 OK.20150301-0000
10 rows selected
SQL>
我正在尝试识别 table TEMP_TEST 中的所有行,其中 COL_A 中的 DATE 小于 SYSDATE - 7.
SQL>
SQL> SELECT * FROM TEMP_TEST T WHERE
TO_DATE(SUBSTR(TRIM(T.COL_A),7,8),'YYYYMMDD') < sysdate-7;
**ORA-01841: (full) year must be between -4713 and +9999, and not be 0**
SQL>
table 仅包含 200 行,因此我目视检查了数据是否存在任何问题。所有日期均有效。这个错误的原因可能是什么?
谢谢
显然所有日期都无效,因此您会收到错误消息。我会尝试类似下面的东西(未经测试,但认为可以),只是为了找出问题记录。
declare
v_date date;
begin
for c in (select col_a from temp_test) loop
begin
v_date := to_date(substr(trim(c.col_a),7,8),'YYYYMMDD');
exception when others then
dbms_output.put_line(c.col_a);
end;
end loop;
end;
请注意,使用 others
作为唯一的异常处理程序通常被认为是不良做法。在生产代码中,异常应该单独处理。即使用于调试,输出SQL错误会更好,但对于预计只有几个错误的第一遍,有时偷懒也是可以的。
使用显式游标调试数字或日期转换错误通常会很快找到有问题的行(在这里,我伪造了你的 TEMP_TEST table):
declare
cursor l_cur is
with temp_test(col_a) as (
select '20150201_abc' col_a from dual union all
select 'x0150201_abc' col_a from dual union all
select '20150201_abc' col_a from dual)
SELECT * FROM TEMP_TEST T;
l_data l_cur%rowtype;
dummy date;
begin
open l_cur;
loop
fetch l_cur
into l_data;
exit when l_cur%notfound;
begin
dummy := TO_DATE(SUBSTR(TRIM(l_data.COL_A), 1, 8), 'YYYYMMDD');
exception
when others then
dbms_output.put_line(sqlerrm || ' for ' || l_data.col_a);
end;
end loop;
end;
编辑:WHEN OTHERS
仅用于交互式调试目的 - 请不要在生产代码中使用它。
我在 Oracle11g 中有以下 table。
SQL> DESC tmp_test;
Name Type Nullable Default Comments
-------------------- ------------- -------- ------- --------
SERNO NUMBER(10)
CARDNO VARCHAR2(25) Y
COL_A VARCHAR2(255) Y
DATEA DATE Y
DATEB DATE Y
TAG VARCHAR2(255) Y
FEEDBACK CHAR(1) Y
SQL>
SQL> SELECT * FROM (SELECT T.COL_A FROM TEMP_TEST T ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <=10;
COL_A
--------------------------------------------------------------------------------
00 OK.20150301-0000
00 OK.20150301-0000
00 OK.20150301-0000
00 OK.20150205-0000
00 OK.20150301-0000
00 OK.20150301-0000
00 OK.20150213-0000
00 OK.20150301-0000
00 OK.20150129-0000
00 OK.20150301-0000
10 rows selected
SQL>
我正在尝试识别 table TEMP_TEST 中的所有行,其中 COL_A 中的 DATE 小于 SYSDATE - 7.
SQL>
SQL> SELECT * FROM TEMP_TEST T WHERE
TO_DATE(SUBSTR(TRIM(T.COL_A),7,8),'YYYYMMDD') < sysdate-7;
**ORA-01841: (full) year must be between -4713 and +9999, and not be 0**
SQL>
table 仅包含 200 行,因此我目视检查了数据是否存在任何问题。所有日期均有效。这个错误的原因可能是什么?
谢谢
显然所有日期都无效,因此您会收到错误消息。我会尝试类似下面的东西(未经测试,但认为可以),只是为了找出问题记录。
declare
v_date date;
begin
for c in (select col_a from temp_test) loop
begin
v_date := to_date(substr(trim(c.col_a),7,8),'YYYYMMDD');
exception when others then
dbms_output.put_line(c.col_a);
end;
end loop;
end;
请注意,使用 others
作为唯一的异常处理程序通常被认为是不良做法。在生产代码中,异常应该单独处理。即使用于调试,输出SQL错误会更好,但对于预计只有几个错误的第一遍,有时偷懒也是可以的。
使用显式游标调试数字或日期转换错误通常会很快找到有问题的行(在这里,我伪造了你的 TEMP_TEST table):
declare
cursor l_cur is
with temp_test(col_a) as (
select '20150201_abc' col_a from dual union all
select 'x0150201_abc' col_a from dual union all
select '20150201_abc' col_a from dual)
SELECT * FROM TEMP_TEST T;
l_data l_cur%rowtype;
dummy date;
begin
open l_cur;
loop
fetch l_cur
into l_data;
exit when l_cur%notfound;
begin
dummy := TO_DATE(SUBSTR(TRIM(l_data.COL_A), 1, 8), 'YYYYMMDD');
exception
when others then
dbms_output.put_line(sqlerrm || ' for ' || l_data.col_a);
end;
end loop;
end;
编辑:WHEN OTHERS
仅用于交互式调试目的 - 请不要在生产代码中使用它。