在Oracle中订购VARCHAR2日期

时间:2012-05-24 20:54:14

标签: sql oracle

我在VIEW中有一个列,其中包含格式为'MM / DD / YYYY'的日期值。

如果此列仅包含我列出的格式的日期值,我可以在列上ORDER BY的{​​{1}}上执行TO_DATE,以使VIEW按该日期排序:

ORDER BY TO_DATE(MY_DATE_COLUMN, 'MM/DD/YYYY') desc

但是,此列中的数据未格式化为“MM / DD / YYYY”。

是否只是使用SQL才能对此列进行排序,并将其视为DATE列?

我认为由于数据未被格式化为'MM / DD / YYYY'而无法实现,但我并不完全确定......

我不想在VIEW中添加其他列来完成此操作。

4 个答案:

答案 0 :(得分:5)

一种方法是手动验证日期:

order by (case when substr(MY_DATE_COLUMN, 1, 2) between '01' and '12' and
                    substr(my_date_column, 3, 1) = '/' and
                    substr(my_date_column, 4, 2) between '01' and '31' and
                    substr(my_date_column, 5, 1) = '/' and
                    substr(my_date_column, 6, 4) between '1900' and '2100' and
                    len(my_date_column) = 10
               then to_date(MY_DATE_COLUMN, 'mm/dd/yyyy')
          end) desc

这对于大多数用途来说可能已经足够了,尽管它将允许2月30日。

你真正想要的是Oracle中的IsDate函数,但它不可用。

我在发布之后意识到可能有一种更简单的方法:

order by substr(my_date_column, 6, 4) desc, substr(MY_DATE_COLUMN, 1, 2) desc,
         substr(my_date_column, 4, 2) desc

它只提取年,月,日和降序。非日期将混合在一起,具体取决于它们包含的内容。然而,提问者似乎并不关心顺序,只是简单地消除了语法错误。

答案 1 :(得分:4)

您可以在此列上创建一个尝试转换日期的函数,但捕获任何异常,并按此排序。

您还可以嵌套异常并尝试多种格式进行转换,然后默认为您选择的某个日期。例如

CREATE OR REPLACE FUNCTION my2date( p_str in VARCHAR2) RETURN DATE is

BEGIN
      RETURN to_date( p_str, 'MM/DD/YYYY' );
EXCEPTION WHEN OTHERS THEN
    BEGIN
        RETURN to_date( p_str, 'DD/MM/YYYY');
    EXCEPTION WHEN OTHERS THEN
        RETURN sysdate; /* or some other fixed date - depends on if you want these first or last */
    END;
END;
/

然后使用条款:

ORDER BY my2date(MY_DATE_COLUMN) desc;

答案 2 :(得分:2)

如何修复数据,并添加触发器以防止进一步的错误数据...... 或添加适当的日期列而不是varchar ...

答案 3 :(得分:2)

实现此目的的最简单方法可能是定义自己的to_date()函数,该函数返回null(或任何其他默认值,如sysdate)。这是可能的,因为to_date在无法处理输入值时会抛出异常。

CREATE OR REPLACE FUNCTION to_date_null(date_str IN varchar2, format_mask IN varchar2)
RETURN DATE
IS
  l_date DATE;
BEGIN
  l_date := to_date( date_str, format_mask );
  RETURN l_date;
EXCEPTION
  WHEN others THEN
    RETURN null;
END to_date_null;

然后您可以在order by子句

中使用此功能
order by to_date_null(MY_DATE_COLUMN, 'MM/DD/YYYY') desc NULLS LAST;

通过指定NULLS FIRSTNULLS LAST,您可以定义非日期值的放置位置。