使用 CAST 时格式化日期
Formatting date when using CAST
我想使用 CAST
将 DATE
类型转换为 VARCHAR2
类型。
DBUSER >SELECT CAST(CURRENT_DATE AS VARCHAR2(20)) THE_DATE from DUAL;
THE_DATE
--------------------
09-AUG-17
但是,我需要将 VARCHAR2 结果格式化为 'YYYYMM'。我知道我可以通过更改会话日期格式来实现此效果,但我宁愿不这样做。
DBUSER >ALTER SESSION SET NLS_DATE_FORMAT = 'YYYYMM';
Session altered.
DBUSER >SELECT CAST(CURRENT_DATE AS VARCHAR2(20)) THE_DATE from DUAL;
THE_DATE
--------------------
201708
我想避免使用 Oracle 专有的 TO_CHAR() 函数。有人对如何做到这一点有建议吗?
这可能对你有帮助:
SELECT extract(year from CURRENT_DATE) || case when extract(month from CURRENT_DATE) <10 THEN '0' || extract(month from CURRENT_DATE) END THE_DATE from DUAL;
I am trying to standardize on ANSI SQL to the degree possible and avoid proprietary vendor nonstandard implementations.
ANSI SQL92 standard 中没有指定将 DATETIME
数据类型格式化为字符串的函数。
最简单的解决方案是使用 Oracle 为此目的提供的功能:
SELECT TO_CHAR( yourdate, 'YYYYMM' ) FROM yourtable;
但是,您可以使用 EXTRACT
函数(符合 ANSI 标准)获取年份和月份的组成部分:
SELECT EXTRACT( YEAR FROM yourdate ),
EXTRACT( MONTH FROM yourdate )
FROM yourtable;
然后您需要将数字转换为字符串并连接字符串:
SELECT TO_CHAR( EXTRACT( YEAR FROM yourdate ) )
|| TO_CHAR( EXTRACT( MONTH FROM yourdate ) )
FROM yourtable
但你试图避免 TO_CHAR
所以你可以这样做:
SELECT CAST( EXTRACT( YEAR FROM yourdate ) AS VARCHAR2(4) )
|| CAST( EXTRACT( MONTH FROM yourdate ) AS VARCHAR2(2) )
FROM yourtable
或者,使用隐式转换
SELECT EXTRACT( YEAR FROM yourdate )
|| EXTRACT( MONTH FROM yourdate )
FROM yourtable
但是,如果年份不是4位数字或者月份不是2位数字,那么您需要填充这些值;同样,简单的解决方案是 TO_CHAR
:
SELECT TO_CHAR( EXTRACT( YEAR FROM yourdate ), 'FM0000' )
|| TO_CHAR( EXTRACT( MONTH FROM yourdate ), 'FM00' )
FROM yourtable
或LPAD
:
SELECT LPAD( EXTRACT( YEAR FROM yourdate ), 4, '0' )
|| LPAD( EXTRACT( MONTH FROM yourdate ), 4, '0' )
FROM yourtable
但这些都不在 ANSI
标准中,所以:
SELECT CASE
WHEN EXTRACT( YEAR FROM yourdate ) < 10 THEN '000'
WHEN EXTRACT( YEAR FROM yourdate ) < 100 THEN '00'
WHEN EXTRACT( YEAR FROM yourdate ) < 1000 THEN '0'
ELSE NULL
END
|| EXTRACT( YEAR FROM yourdate )
|| CASE
WHEN EXTRACT( MONTH FROM yourdate ) < 10 THEN '0'
END
|| EXTRACT( MONTH FROM yourdate )
FROM yourtable;
而且我们已经成功地将单个 Oracle 函数转换为 ANSI 兼容表达式的庞然大物。
但是,Oracle 的 DATE
数据类型不符合 ANSI 标准(它是 ANSI DATE
和 TIME
数据类型的串联)所以我会问它是否是值得 - 特别是如果您随后考虑显示日期的时间部分(除非您首先使用 CAST
将 DATE
转换为 TIMESTAMP
,否则 EXTRACT
不会提取) .
SELECT TO_CHAR( yourdate, 'YYYYMMDDHH24MISS' ) FROM yourtable
或
SELECT CASE
WHEN EXTRACT( YEAR FROM yourdate ) < 10 THEN '000'
WHEN EXTRACT( YEAR FROM yourdate ) < 100 THEN '00'
WHEN EXTRACT( YEAR FROM yourdate ) < 1000 THEN '0'
ELSE NULL
END
|| EXTRACT( YEAR FROM yourdate )
|| CASE
WHEN EXTRACT( MONTH FROM yourdate ) < 10 THEN '0'
END
|| EXTRACT( MONTH FROM yourdate )
|| CASE
WHEN EXTRACT( DAY FROM yourdate ) < 10 THEN '0'
END
|| EXTRACT( DAY FROM yourdate )
|| CASE
WHEN EXTRACT( HOUR FROM CAST( yourdate AS TIMESTAMP ) ) < 10 THEN '0'
END
|| EXTRACT( HOUR FROM CAST( yourdate AS TIMESTAMP ) )
|| CASE
WHEN EXTRACT( MINUTE FROM CAST( yourdate AS TIMESTAMP ) ) < 10 THEN '0'
END
|| EXTRACT( MINUTE FROM CAST( yourdate AS TIMESTAMP ) )
|| CASE
WHEN EXTRACT( SECOND FROM CAST( yourdate AS TIMESTAMP ) ) < 10 THEN '0'
END
|| EXTRACT( SECOND FROM CAST( yourdate AS TIMESTAMP ) )
FROM yourtable;
[TL/DR] 只需使用 TO_CHAR
我想使用 CAST
将 DATE
类型转换为 VARCHAR2
类型。
DBUSER >SELECT CAST(CURRENT_DATE AS VARCHAR2(20)) THE_DATE from DUAL;
THE_DATE
--------------------
09-AUG-17
但是,我需要将 VARCHAR2 结果格式化为 'YYYYMM'。我知道我可以通过更改会话日期格式来实现此效果,但我宁愿不这样做。
DBUSER >ALTER SESSION SET NLS_DATE_FORMAT = 'YYYYMM';
Session altered.
DBUSER >SELECT CAST(CURRENT_DATE AS VARCHAR2(20)) THE_DATE from DUAL;
THE_DATE
--------------------
201708
我想避免使用 Oracle 专有的 TO_CHAR() 函数。有人对如何做到这一点有建议吗?
这可能对你有帮助:
SELECT extract(year from CURRENT_DATE) || case when extract(month from CURRENT_DATE) <10 THEN '0' || extract(month from CURRENT_DATE) END THE_DATE from DUAL;
I am trying to standardize on ANSI SQL to the degree possible and avoid proprietary vendor nonstandard implementations.
ANSI SQL92 standard 中没有指定将 DATETIME
数据类型格式化为字符串的函数。
最简单的解决方案是使用 Oracle 为此目的提供的功能:
SELECT TO_CHAR( yourdate, 'YYYYMM' ) FROM yourtable;
但是,您可以使用 EXTRACT
函数(符合 ANSI 标准)获取年份和月份的组成部分:
SELECT EXTRACT( YEAR FROM yourdate ),
EXTRACT( MONTH FROM yourdate )
FROM yourtable;
然后您需要将数字转换为字符串并连接字符串:
SELECT TO_CHAR( EXTRACT( YEAR FROM yourdate ) )
|| TO_CHAR( EXTRACT( MONTH FROM yourdate ) )
FROM yourtable
但你试图避免 TO_CHAR
所以你可以这样做:
SELECT CAST( EXTRACT( YEAR FROM yourdate ) AS VARCHAR2(4) )
|| CAST( EXTRACT( MONTH FROM yourdate ) AS VARCHAR2(2) )
FROM yourtable
或者,使用隐式转换
SELECT EXTRACT( YEAR FROM yourdate )
|| EXTRACT( MONTH FROM yourdate )
FROM yourtable
但是,如果年份不是4位数字或者月份不是2位数字,那么您需要填充这些值;同样,简单的解决方案是 TO_CHAR
:
SELECT TO_CHAR( EXTRACT( YEAR FROM yourdate ), 'FM0000' )
|| TO_CHAR( EXTRACT( MONTH FROM yourdate ), 'FM00' )
FROM yourtable
或LPAD
:
SELECT LPAD( EXTRACT( YEAR FROM yourdate ), 4, '0' )
|| LPAD( EXTRACT( MONTH FROM yourdate ), 4, '0' )
FROM yourtable
但这些都不在 ANSI
标准中,所以:
SELECT CASE
WHEN EXTRACT( YEAR FROM yourdate ) < 10 THEN '000'
WHEN EXTRACT( YEAR FROM yourdate ) < 100 THEN '00'
WHEN EXTRACT( YEAR FROM yourdate ) < 1000 THEN '0'
ELSE NULL
END
|| EXTRACT( YEAR FROM yourdate )
|| CASE
WHEN EXTRACT( MONTH FROM yourdate ) < 10 THEN '0'
END
|| EXTRACT( MONTH FROM yourdate )
FROM yourtable;
而且我们已经成功地将单个 Oracle 函数转换为 ANSI 兼容表达式的庞然大物。
但是,Oracle 的 DATE
数据类型不符合 ANSI 标准(它是 ANSI DATE
和 TIME
数据类型的串联)所以我会问它是否是值得 - 特别是如果您随后考虑显示日期的时间部分(除非您首先使用 CAST
将 DATE
转换为 TIMESTAMP
,否则 EXTRACT
不会提取) .
SELECT TO_CHAR( yourdate, 'YYYYMMDDHH24MISS' ) FROM yourtable
或
SELECT CASE
WHEN EXTRACT( YEAR FROM yourdate ) < 10 THEN '000'
WHEN EXTRACT( YEAR FROM yourdate ) < 100 THEN '00'
WHEN EXTRACT( YEAR FROM yourdate ) < 1000 THEN '0'
ELSE NULL
END
|| EXTRACT( YEAR FROM yourdate )
|| CASE
WHEN EXTRACT( MONTH FROM yourdate ) < 10 THEN '0'
END
|| EXTRACT( MONTH FROM yourdate )
|| CASE
WHEN EXTRACT( DAY FROM yourdate ) < 10 THEN '0'
END
|| EXTRACT( DAY FROM yourdate )
|| CASE
WHEN EXTRACT( HOUR FROM CAST( yourdate AS TIMESTAMP ) ) < 10 THEN '0'
END
|| EXTRACT( HOUR FROM CAST( yourdate AS TIMESTAMP ) )
|| CASE
WHEN EXTRACT( MINUTE FROM CAST( yourdate AS TIMESTAMP ) ) < 10 THEN '0'
END
|| EXTRACT( MINUTE FROM CAST( yourdate AS TIMESTAMP ) )
|| CASE
WHEN EXTRACT( SECOND FROM CAST( yourdate AS TIMESTAMP ) ) < 10 THEN '0'
END
|| EXTRACT( SECOND FROM CAST( yourdate AS TIMESTAMP ) )
FROM yourtable;
[TL/DR] 只需使用 TO_CHAR