Sql ORA-01841:(完整)年份必须介于-4713和+之间;9999,而不是0个提示
我想对表Sql ORA-01841:(完整)年份必须介于-4713和+之间;9999,而不是0个提示,sql,oracle,Sql,Oracle,我想对表test\u tbl中DATUM列中大于01.01.2020的所有值进行分组。运行查询时: SELECT to_date("DATUM", 'YYYYMM') FROM test_tbl WHERE to_date("DATUM", 'YYYYMM') >= to_date('2020-01-01' ,'YYYY-MM-DD') GROUP BY to_date("DATUM", 'YYYYMM') 我得到以下错误 OR
test\u tbl
中DATUM
列中大于01.01.2020的所有值进行分组。运行查询时:
SELECT to_date("DATUM", 'YYYYMM')
FROM test_tbl
WHERE to_date("DATUM", 'YYYYMM') >= to_date('2020-01-01' ,'YYYY-MM-DD')
GROUP BY to_date("DATUM", 'YYYYMM')
我得到以下错误
ORA-01841:(完整)年份必须介于-4713和+9999之间,而不是0
表test\u tbl
如下所示:
基准面(varchar2)
201701
202001
201901
201801
202003
您的基准列只需要包含数字数据,就可以按照您指定的格式作为日期进行处理。加上最后两位数字需要介于01和12之间;但这是一个单独的问题,因为您的错误消息正在抱怨年的值 因此,您可以使用以下方法检查无效值:
SELECT
datum
,LENGTH(REGEXP_REPLACE(datum,'[0-9]','')) as char_count
FROM test_tbl
WHERE LENGTH(REGEXP_REPLACE(datum,'[0-9]','')) > 0
;
应该可以相当快地旋转300k行。这是一个数据错误。在基准列的某个地方,有一个不能转换为日期的字符串。当我们将数据存储为错误的数据类型时,这总是一个风险 如果您使用的是Oracle 12c R2或更高版本,您可以通过以下查询轻松找到错误行:
select * from your_table
where validate_conversion(datum as date, 'yyyymm') = 0
如果您使用的是早期版本的数据库,则可以创建一个执行类似操作的函数
create or replace function is_date(p_str in varchar2
,p_mask in varchar2 := 'yyyymm' ) return number is
n pls_integer;
begin
declare
dt date;
begin
dt := to_date(p_str, p_mask);
n := 1;
exception
when others then
n := 0;
end;
return n;
end;
/
类似于validate\u conversion()
这将返回1表示有效日期,0表示无效日期
select * from your_table
where is_date(datum, 'yyyymm') = 0
这种方法更安全,因为它应用了Oracle的实际日期验证机制。然而,使用模式匹配正则表达式等使我们容易遇到弱模式,这些弱模式会传递无法转换为日期的字符串。请用英语重新发布。数据的数据类型是什么?如果它不是VARCHAR2,那么您不应该使用TOU DATE,它将VARCHAR2作为其第一个输入参数。它的VARCHAR2,同样当我将列转换为日期数据类型时,我会得到错误列
数据的数据类型是什么?如果它是一个VARCHAR2
或数字,那么:究竟为什么要将数据值存储为字符串,请使用适当的DATE
格式。如果是日期
,则:决不要对已经是日期的值调用TO_DATE
。请详细说明你的问题。真的只有5行测试数据吗?我之所以这样做,是因为我能够创建您的表,添加5行,并毫无疑问地运行您的查询。结果为2020-01-01和2020-03-01。另外,这里分组的目的是什么?++我同意VALIDATE_转换是一个更优雅的解决方案。VALIDATE_转换正在工作,但我只得到一个空结果。这意味着对于有效日期,它只返回“1”。我还能做什么?第二个解决方案也会导致一个空结果,因为其中长度(REGEXP_REPLACE(datum,[0-9],'')>0
将是最慢的解决方案之一。