我们如何仅从 Oracle 中具有各种日期和字符串格式的列中提取日期?
Posted
技术标签:
【中文标题】我们如何仅从 Oracle 中具有各种日期和字符串格式的列中提取日期?【英文标题】:How can we extract date only from a column with various date and string formats in Oracle? 【发布时间】:2021-12-09 07:28:08 【问题描述】:ACTUAL | expected |
---|---|
SEP-10-2017 | 10-SEP-2017 |
SEP 30 2018 | 30-SEP-2018 |
OFFICE OF SMALL | |
OCT-11-2018 | 11-OCT-2018 |
O9-SEP-2009 | O9-SEP-2009 |
Not Applicable | |
NOV-20-2001 | 20-NOV-2001 |
BANIJYA BHIBAG | |
AUGUST 03 2017 | 03-AUG-2017 |
AUG-04-1991 | 04-AUG-1991 |
97/2015 | |
09/09/2018 | 09-SEP-2018 |
我们如何才能得到如上的结果并丢弃无法转换的日期?
【问题讨论】:
嗨,尼泊尔,请在“问汤姆”asktom.oracle.com/pls/apex/… 上查看这个答案 【参考方案1】:从 Oracle 12 开始,您不需要 PL/SQL 并且可以使用:
SELECT actual,
COALESCE(
TO_DATE(
actual DEFAULT NULL ON CONVERSION ERROR,
'MM-DD-YYYY',
'NLS_DATE_LANGUAGE=ENGLISH'
),
TO_DATE(
actual DEFAULT NULL ON CONVERSION ERROR,
'DD-MON-YYYY',
'NLS_DATE_LANGUAGE=ENGLISH'
)
) AS parsed
FROM table_name;
其中,对于样本数据:
CREATE TABLE table_name (ACTUAL) AS
SELECT 'SEP-10-2017' FROM DUAL UNION ALL
SELECT 'SEP 30 2018' FROM DUAL UNION ALL
SELECT 'OFFICE OF SMALL' FROM DUAL UNION ALL
SELECT 'OCT-11-2018' FROM DUAL UNION ALL
SELECT 'O9-SEP-2009' FROM DUAL UNION ALL
SELECT 'Not Applicable' FROM DUAL UNION ALL
SELECT 'NOV-20-2001' FROM DUAL UNION ALL
SELECT 'BANIJYA BHIBAG' FROM DUAL UNION ALL
SELECT 'AUGUST 03 2017' FROM DUAL UNION ALL
SELECT 'AUG-04-1991' FROM DUAL UNION ALL
SELECT '97/2015' FROM DUAL UNION ALL
SELECT '09/09/2018' FROM DUAL;
输出:
ACTUAL PARSED SEP-10-2017 10-SEP-2017 SEP 30 2018 30-SEP-2018 OFFICE OF SMALL OCT-11-2018 11-OCT-2018 O9-SEP-2009 Not Applicable NOV-20-2001 20-NOV-2001 BANIJYA BHIBAG AUGUST 03 2017 03-AUG-2017 AUG-04-1991 04-AUG-1991 97/2015 09/09/2018 09-SEP-2018
注意:O9-SEP-2009
尚未解析,因为您将字母 O
而不是数字 0
作为第一个字符。
db小提琴here
【讨论】:
@MTO 做得很好 @MT0 ,按预期工作。【参考方案2】:一种选择是创建一个涵盖所有可能组合的函数。以下示例包含其中一些 - 您必须在找到它们时添加新的。
SQL> create or replace function f_date (par_str in varchar2)
2 return date
3 is
4 l_date date;
5 begin
6 begin
7 l_date := to_date(par_str, 'mon-dd-yyyy');
8 return l_date;
9 exception
10 when others then null;
11 end;
12
13 --
14
15 begin
16 l_date := to_date(par_str, 'mon dd yyyy');
17 return l_date;
18 exception
19 when others then null;
20 end;
21
22 --
23
24 begin
25 l_date := to_date(par_str, 'dd-mon-yyyy');
26 return l_date;
27 exception
28 when others then null;
29 end;
30
31 --
32
33 begin
34 l_date := to_date(par_str, 'month dd yyyy');
35 return l_date;
36 exception
37 when others then null;
38 end;
39
40 --
41
42 begin
43 l_date := to_date(par_str, 'dd/mm/yyyy');
44 return l_date;
45 exception
46 when others then null;
47 end;
48
49 return null;
50
51 exception
52 when others then
53 return null;
54 end f_date;
55 /
Function created.
测试:
SQL> select actual, f_date(actual) as expected
2 from test;
ACTUAL EXPECTED
--------------- -----------
SEP-10-2017 10-SEP-2017
SEP 30 2018 30-SEP-2018
OFFICE OF SMALL
09-SEP-2009 09-SEP-2009
Not applicable
AUGUST 03 2017 03-AUG-2017
97/2015
09/09/2018 09-SEP-2018
8 rows selected.
SQL>
可能的问题:如果actual = 09/10/12
,是什么?
那么,它是什么?
2012 年 10 月 9 日 2012 年 9 月 10 日 2009 年 10 月 12 日 ...【讨论】:
【参考方案3】:如果您确定对于可以转换为日期值的值没有任何其他类型的格式(例如,所有数据都符合此示例数据集),请使用下面的代码块是为了在另一个表(t2
)中填充合适的日期值,同时显示腐烂的值,例如
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
dt DATE;
BEGIN
FOR c IN (SELECT * FROM t) LOOP
BEGIN
dt := TO_DATE(c.col, 'MON-DD-YYYY', 'NLS_DATE_LANGUAGE=ENGLISH');
INSERT INTO t2 VALUES(c.id,c.col);
EXCEPTION
WHEN OTHERS THEN
BEGIN
dt := TO_DATE(c.col, 'DD/MM/YYYY', 'NLS_DATE_LANGUAGE=ENGLISH');
INSERT INTO t2 VALUES(c.id,c.col);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(c.col || ' is not a valid date value');
END;
END;
END LOOP;
COMMIT;
END;
/
Demo
【讨论】:
以上是关于我们如何仅从 Oracle 中具有各种日期和字符串格式的列中提取日期?的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 2008 仅从字段中选择日期 [重复]