英文:
CONVERT NUMBER(10) FIELD IN ORACLE SQL TO DATE
问题
我有一个表格,其中日期字段以数字形式存储(20161231 = 12/31/2016)。我想将这个字段转换为日期。我尝试了以下方法,但收到了错误消息。
,TO_CHAR(TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD'), 'mm/dd/yyyy') AS CHEM_DATE
错误:ORA-01847:月份的天数必须在1到月份的最后一天之间。
我尝试了几种方法,但都无济于事。感谢您的帮助。
英文:
I have a table where the date field is stored as a number (20161231 = 12/31/2016). I would like to convert this field to a date. I have tried the following, but have received error messages.
,TO_CHAR(TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD'), 'mm/dd/yyyy') AS CHEM_DATE
Error: ORA-01847: day of month must be between 1 and last day of month
I have tried several things to no avail. Thanks for your assistance
答案1
得分: 3
当你对一个数字使用 TO_DATE
时,它会隐式地将数字转换为 varchar2
,然后将其传递给 TO_DATE
。只要你的数字始终有8位数(会在单个数字的月份和日期前补零),并且它所表示的日期实际上存在于日历中,它就能工作,尽管依赖隐式类型转换有点不够规范。在这种情况下,最好明确使用 TO_CHAR
以提高代码的清晰度。但无论如何,你的代码是有效的。
因此,你的数据中必定存在一个错误的数值日期。要找到它,可以执行以下查询:
SELECT *
FROM (
SELECT TO_DATE(tr.chemo_date DEFAULT NULL ON CONVERSION ERROR,'YYYYMMDD') converted_date, tr.*
FROM mytable tr
)
WHERE converted_date IS NULL
AND chemo_date IS NOT NULL
你还可以创建一个捕获异常的函数来完成相同的操作:
CREATE OR REPLACE FUNCTION f_safe_int_to_date(in_char IN integer, in_format IN varchar2)
RETURN date
AS
BEGIN
var_date := TO_DATE(in_char, in_format);
RETURN var_date;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
/
SELECT tr.*
FROM mytable tr
WHERE f_safe_int_to_date(tr.chemo_date, 'YYYYMMDD') IS NULL
AND tr.chemo_date IS NOT NULL;
一旦找到问题值,你可以分析数据问题并解决它。
英文:
When you to a TO_DATE
on a number, it implicitly casts the number to varchar2
and then passes that in to TO_DATE
. As long as your number always had 8 digits (zero pads single digit months and days), and the date it represents actually exists on the calendar, it will work, though it is a bit sloppy to rely on implicit type conversions. It's better for clarity to be explicit about a TO_CHAR
in a situation like this. But still, your code works.
So, you must have a bad numeric-date in your data. To find it, query:
SELECT *
FROM (SELECT TO_DATE(tr.chemo_date DEFAULT NULL ON CONVERSION ERROR,'YYYYMMDD') converted_date,
tr.*
FROM mytable tr)
WHERE converted_date IS NULL
AND chemo_date IS NOT NULL
You can also create a function that traps exceptions to accomplish the same thing:
CREATE OR REPLACE FUNCTION f_safe_int_to_date(in_char IN integer,in_format IN varchar2)
RETURN date
AS
BEGIN
var_date := TO_DATE(in_char,in_format);
RETURN var_date;
EXCEPTION
WHEN OTHERS THEN
RETURN NULL;
END;
/
SELECT tr.*
FROM mytable tr
WHERE f_safe_int_to_date(tr.chemo_date,'YYYYMMDD') IS NULL
AND tr.chemo_date IS NOT NULL
Once you identify the problem values you can probably figure out your data issue and resolve it.
答案2
得分: 2
如果您的列是一个 NUMBER
类型,那么请使用 TO_DATE
来将其转换为日期:
TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD')
注意:不清楚为什么您在格式中只有8位数字时使用了 NUMBER(10)
。
在Oracle中,DATE
是一个二进制数据类型,由7个字节组成,分别表示世纪、世纪年份、月份、日期、小时、分钟和秒。它始终包含这7个组件,永远不会以任何特定格式存储。
如果您想以特定的格式显示一个 DATE
,则可以选择以下方式之一:
-
更改您正在使用的客户端应用程序的设置,以允许其以特定方式格式化日期。
如果您使用的是SQL*Plus或SQL Developer,则可以使用以下命令:
ALTER SESSION SET NLS_DATE_FORMAT='mm/dd/yyyy';
然后使用上面的查询。
如果您使用的是另一个客户端应用程序,请查阅该应用程序的文档。
-
使用
TO_CHAR
将DATE
转换为字符串(但这样它将不再是DATE
):TO_CHAR(TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD'), 'mm/dd/yyyy') AS CHEM_DATE
(与您在问题中所做的完全一样)
英文:
If your column is a NUMBER
then use TO_DATE
to convert it to a date:
TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD')
Note: it is unclear why you are using NUMBER(10)
when the format only has 8 digits.
In Oracle, a DATE
is a binary data-type that consists of 7 bytes representing century, year-of-century, month, day, hour, minute and second. It ALWAYS has those 7 components and it is NEVER stored in any particular format.
If you want to display a DATE
in a specific format then either:
-
Change the settings of the client application you are using to access the database to allow it to format the date in a specific way.
If you are using SQL*Plus or SQL Developer then you can use:
ALTER SESSION SET NLS_DATE_FORMAT='mm/dd/yyyy';
Then use the query above.
If you are using another client application then consult the documentation for that application.
-
Convert the
DATE
to a string usingTO_CHAR
(but then it will not be aDATE
):TO_CHAR(TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD'), 'mm/dd/yyyy') AS CHEM_DATE
(Exactly as you did in the question)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论