nts*_*sue 8 oracle crystal-reports
我有以下查询,我试图在我正在处理的水晶报表中用作COMMAND.
SELECT * FROM myTable
WHERE to_date(myTable.sdate, 'MM/dd/yyyy') <= {?EndDate}
Run Code Online (Sandbox Code Playgroud)
这很好用,但我唯一担心的是日期可能并不总是格式正确(由于用户错误).我知道当to_date函数失败时会抛出异常..是否有可能以忽略SELECT语句中相应行的方式处理此异常?因为如果整个数据库中只有一个日期格式不正确,我的报告就会中断.
我查看Oracle是否提供了isDate函数,但看起来您应该只处理异常.任何帮助将不胜感激.谢谢!!
Jus*_*ave 25
回应Tony的评论,你最好不要在DATE列中存储日期,而不是强迫前端查询工具查找和处理这些异常.
但是,如果您遇到错误的数据模型,最简单的选择是创建一个执行转换并处理错误的函数,
CREATE OR REPLACE FUNCTION my_to_date( p_date_str IN VARCHAR2,
p_format_mask IN VARCHAR2 )
RETURN DATE
IS
l_date DATE;
BEGIN
l_date := to_date( p_date_str, p_format_mask );
RETURN l_date;
EXCEPTION
WHEN others THEN
RETURN null;
END my_to_date;
Run Code Online (Sandbox Code Playgroud)
您的查询将成为
SELECT *
FROM myTable
WHERE my_to_date(myTable.sdate, 'MM/dd/yyyy') <= {?EndDate}
Run Code Online (Sandbox Code Playgroud)
当然,您最有可能想要在MY_TO_DATE调用上使用基于函数的索引,以使此查询合理有效.
如果您的数据不一致且存储为字符串的日期可能无效,那么您有3个选项.
我建议使用第一个选项,因为您的数据应该是一致的.
第二个选项将提供一些灵活性和速度,因为报告只会获取所需的行.
第三个选项将强制报告获取表中的每个记录,然后让报告过滤掉记录.
我也有同样的问题...一个旧的遗留数据库,其中包含日期的 varchar 字段和该字段中数十年的错误数据。尽管我很愿意,但我也无法更改数据类型。但我想出了这个解决方案来查找日期是否是最新的,这似乎也是您正在做的事情:
select * from MyTable
where regexp_like(sdate, '[0-1][0-9].[0-3][0-9].[0-9][0-9][0-9][0-9]')
-- make sure it's in the right format and ignore rows that are not
and substr(sdate,7,10) || substr(sdate,1,2) || substr(sdate,4,5) >= to_char({?EndDate}, 'YYYYMMDD')
-- put the date in ISO format and do a string compare
Run Code Online (Sandbox Code Playgroud)
这种方法的好处是不会因为“2 月 30 日”这样的日期而感到窒息。
从 Oracle 12c 开始,无需定义函数来捕获转换异常。
Oracle在函数ON CONVERSION ERROR中引入了一个子句TO_DATE。
基本上,该子句会抑制无效日期字符串转换中的错误(典型错误是ORA-01843, ORA-01841, ORA-011861, ORA-01840)并返回指定的默认值或 null。
使用示例
select to_date('2020-99-01','yyyy-mm-dd') from dual;
-- ORA-01843: not a valid month
select to_date('2020-99-01' default null on conversion error,'yyyy-mm-dd') from dual;
-- returns NULL
select to_date('2020-99-01' default '2020-01-01' on conversion error,'yyyy-mm-dd') from dual;
-- 01.01.2020 00:00:00
Run Code Online (Sandbox Code Playgroud)
遗留应用程序的解决方案
假设有一个表,其中日期列存储为 VARCHAR2(10)
select * from tab;
DATE_CHAR
----------
2021-01-01
2021-99-01
Run Code Online (Sandbox Code Playgroud)
使用上述功能VIRTUAL定义了 DATE 列,该列要么显示日期,要么NULL显示转换错误
alter table tab add (
date_d DATE as (to_date(date_char default null on conversion error,'yyyy-mm-dd')) VIRTUAL
);
select * from tab;
DATE_CHAR DATE_D
---------- -------------------
2021-01-01 01.01.2021 00:00:00
2021-99-01
Run Code Online (Sandbox Code Playgroud)
该VIRTUAL列可以安全使用,因为它的格式是DATE,如果需要,可以在其上设置索引。
select * from tab where date_d = date'2021-01-01';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
31972 次 |
| 最近记录: |