将Oracle SQL中的NUMBER(10)字段转换为日期。

huangapple go评论64阅读模式
英文:

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,则可以选择以下方式之一:

  1. 更改您正在使用的客户端应用程序的设置,以允许其以特定方式格式化日期。

    如果您使用的是SQL*Plus或SQL Developer,则可以使用以下命令:

    ALTER SESSION SET NLS_DATE_FORMAT='mm/dd/yyyy';
    

    然后使用上面的查询。

    如果您使用的是另一个客户端应用程序,请查阅该应用程序的文档。

  2. 使用 TO_CHARDATE 转换为字符串(但这样它将不再是 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:

  1. 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.

  2. Convert the DATE to a string using TO_CHAR (but then it will not be a DATE):

    TO_CHAR(TO_DATE(TR.CHEMO_DATE, 'YYYYMMDD'), 'mm/dd/yyyy') AS CHEM_DATE
    

    (Exactly as you did in the question)

huangapple
  • 本文由 发表于 2023年6月6日 05:38:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定