ORACLE 将字符串转换为未知格式的日期

问题描述 投票:0回答:2

我们有一个传入文件,其中有一个字段,该字段是保存日期值的字符串。字符串(日期值)可以是任意数量的格式。我们需要首先将该值转换为日期,以便我们可以按照我们需要的方式格式化该日期。

在 SQL Server 中我们可以:

SELECT FORMAT(CAST('stringvalue' as date),'yyyyMM') AS MyDate

这几乎适用于我们尝试过的不同类型日期格式的所有测试用例。

但是,ORACLE 似乎您需要首先了解 StringValue 的日期格式,然后才能成功转换它。

SELECT to_char(to_date('stringvalue','MM/DD/YYYY'),'YYYYMM') AS dt 
from dual;

在 ORACLE 中我们有什么办法可以在不知道上面的“MM/DD/YYYY”部分的情况下做到这一点吗??

string oracle date
2个回答
1
投票

如果你想获取不同掩码中的日期,则没有办法做到这一点。如果您想避免使用掩码,只有一种方法可以做到这一点,但它会影响该会话中的所有语句。您可以指定会话级别 nls_date_format,然后使用 CAST 您不需要指定任何掩码

SQL> alter session set nls_date_format='dd/mm/yyyy' ;

Session altered.

SQL> select cast('10/01/2020' as date) from dual ;

CAST('10/0
----------
10/01/2020

但是,它不会接受任何其他掩码,因为采用默认掩码

SQL> select cast('2020/01/10' as date) from dual ;
select cast('2020/01/10' as date) from dual
            *
ERROR at line 1:
ORA-01861: literal does not match format string

但这在 SQL Server 中也会发生。 SQL SERVER 函数 FORMAT(CAST string as date) mask ) 或多或少执行相同的操作,但顺序相反。

  • cast 将掩码转换为日期(使用默认的 SET DATEFORMAT )
  • format 根据您想要的格式将日期转换为字符串。

让我举个例子来说明

SELECT CAST('03/11/2020' AS date); 

2020-03-11

它返回 11 月 3 日,而对我来说,我指的是 3 月 11 日。为什么 ?因为 SQL Server 也会在 SET DATEFORMAT 中中继来更改日期格式的会话级别设置。

没有任何计算语言可以做到这一点。必须隐式或显式提供掩码。 SQL 与任何其他语言一样,无法理解我所说的 3/11 的含义(无论是 11 月 3 日还是 3 月 11 日,两者都可以)。


0
投票

您可以尝试分析您的文本值,以查看您拥有哪种日期格式。

执行类似操作的示例查询如下所示:

WITH subq AS (
   SELECT
      txt_date_value,
      REGEXP_REPLACE(REGEXP_REPLACE(txt_date_value, '[a-zA-Z]', 'A'), '\d', 'd') AS reg_reduced
   FROM data_table
   )
SELECT 
   reg_reduced, 
   COUNT(1), 
   MIN(txt_date_value), 
   MAX(txt_date_value)
FROM subq
GROUP BY reg_reduced
ORDER BY 1
;

一旦获得(最有可能的)日期格式列表,您可以将它们全部放入存储函数(当然,作为正确格式的正则表达式)以根据这些格式转换为日期:

CREATE OR REPLACE FUNCTION text_to_date(p_date_str IN VARCHAR2) RETURN DATE
IS
    v_format VARCHAR2(15) := 'OTHER';
BEGIN
    v_format := 
        CASE
            WHEN REGEXP_LIKE (p_date_str, '\d{4}\-\d{1,2}\-\d{1,2}')
                THEN
                 'yyyy-mm-dd'
            WHEN REGEXP_LIKE (p_date_str, '\d{1,2}\-\d{1,2}\-\d{4}')
                THEN
                 'mm-dd-yyyy'
            WHEN REGEXP_LIKE (p_date_str, '\d{1,2} [A-Za-z]{3} \d{4}')
                THEN
                 'dd MON yyyy'
            ELSE
             'OTHER'
        END;
    IF v_format = 'OTHER' THEN 
        RETURN NULL;
    ELSE
        RETURN to_date(p_date_str, v_format);
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        RETURN NULL;
END;

根据需要添加到 v_format CASE 语句。

© www.soinside.com 2019 - 2024. All rights reserved.