简体   繁体   English

如何在oracle中将sysdate月的值转换为数字?

[英]How to convert a sysdate month value to number in oracle?

Im trying to return the CARDS of my CARD table that will expire in the next month. 我正在尝试返回将在下个月到期的我的CARD表的CARDS。 But the problem is that the table has two columns to represent the card date. 但是问题在于该表有两列代表卡的日期。 The columns are EXPIREDAY and EXPIREMONTH ,both are numbers. 列是EXPIREDAY和EXPIREMONTH,都是数字。 So when i do that query i get an error: 因此,当我执行该查询时,我得到一个错误:

   select * from CARD WHERE EXPIREDAY <= sysdate - interval '2' DAY;
   //Oracle error: ORA-00932: inconsistent datatypes: expected NUMBER got DATE

Is there a way to convert the sysdate - interval '2' DAY as Number data type? 有没有一种方法可以将sysdate - interval '2' DAY转换为Number数据类型?

Thanks! 谢谢!

If you want to compare the values as strings you can use this to convert the SYSDATE 如果要将值作为字符串进行比较,则可以使用它来转换SYSDATE

SELECT TO_CHAR(sysdate, 'MM') || TO_CHAR(sysdate, 'DD') MONTH_NUM FROM DUAL
-- gives you "0922"

and this for your numeric columns which will pad with leading zeros if you only have a single digit 这用于您的数字列,如果您只有一位数字的话,它将以前导零填充

SELECT TO_CHAR(9, 'FM00') || TO_CHAR(22, 'FM00') MONTH_NUM FROM DUAL
-- also gives you "0922"

If you have control over the table schema it would be best practise to store both the DAY and MONTH values in a single numeric field, so that 9-SEP would be stored in this column as the numeric value 0922 where the month is first so that the natural ordering is used. 如果您可以控制表模式,则最好的做法是将DAY和MONTH值都存储在一个数字字段中,这样9-SEP将作为数字值0922存储在此列中,因此月份是第一个使用自然排序。

A simple and not necessarily very efficient approach is to convert the day and month values into an actual date, using to_date() , and then compare that with your target date range: 一种简单但不一定非常有效的方法是使用to_date()将日和月值转换为实际日期,然后将其与目标日期范围进行比较:

select * from card
where to_date(lpad(expireday, 2, '0')
  ||'/'|| lpad(expiremonth, 2, '0'), 'DD/MM')
between sysdate and add_months(sysdate, 1);

Which appears to work . 这似乎起作用 But this will have problems if the dates span the end of the year. 但是,如果日期跨到年末,这将有问题。 Because your table doesn't specify the year, you either have to work one out, or allow to_date to default it to the current year. 由于您的表格未指定年份,因此您必须计算一个年份,或者允许to_date将其默认为当前年份。 And if you let it default then it won't work. 而且,如果您将其设为默认值,则它将无法正常工作。 For example, if you have values for December and January in your table, and run this query in December, then the January dates will be seen as January 2014, and won't be counted as being in the next month. 例如,如果您在表中具有12月和1月的值,并在12月运行此查询,则1月的日期将被视为2014年1月,而不会计入下个月。 So you'll need to do more to pick the right year. 因此,您需要做更多的事情来选择合适的年份。

This treats any month numbers before the current one as being next year, which may be good enough for you as you only have a one-month window: 这会将当前月份之前的任何月份数字都视为明年 ,这可能对您已经足够,因为您只有一个月的时间范围:

select * from card
where to_date(lpad(expireday, 2, '0')
  ||'/'|| lpad(expiremonth, 2, '0')
  ||'/'|| (extract(year from sysdate) +
    case when expiremonth < extract(month from sysdate) then 1 else 0 end),
    'DD/MM/YYYY')
between sysdate and add_months(sysdate, 1);

SQL Fiddle using a date range from December to January. SQL Fiddle使用12月至1月的日期范围。

And you can see the ways the two columns are being combined to form a date in this Fiddle . 您可以在此Fiddle中看到将两列组合在一起以形成日期的方式。

As so often, the moral is... store things as the right data type. 通常,道德是...将事物存储为正确的数据类型。 Store dates as dates, not as string or numbers. 将日期存储为日期,而不是字符串或数字。

Im trying to return the CARDS of my CARD table that will expire in the next month. 我正在尝试返回将在下个月到期的我的CARD表的CARDS。 But the problem is that the table has two columns to represent the card date. 但是问题在于该表有两列代表卡的日期。

Assuming: 假设:

  1. you are using floating months (say: from 23 dec. to 23 jan.) and 您正在使用浮动月份(例如:从12月23日到1月23日),并且
  2. your table somehow only contains one (floating ?) year of data 您的表以某种方式仅包含一年(浮动)的数据

Why can't you use simple arithmetics? 为什么不能使用简单的算术? Like that: 像那样:

-- some constant definitions for testing purpose
with cst as (
  select EXTRACT(DAY from TO_DATE('23/12','DD/MM')) as theDay,
         EXTRACT(MONTH from TO_DATE('23/12','DD/MM')) as theMonth
  from dual)

-- the actual query
select card.* from card,cst 
  where (expiremonth = theMonth AND expireday > theDay)
     or (expiremonth = 1+MOD(theMonth,12) AND expireday <= theDay);
  --                   ^^^^^^^^^^^^^^^^^^
  --            map [01 .. 12] to [02 .. 12, 01] (i.e.: next month)

This will simply select all "pseudo-dates" from tomorrow to the end of the month, as well as any one before (and including) the current day# next month. 这将简单地选择从明天到月末的所有“伪日期”,以及下个月的当前日期(包括该日)之前的任何“伪日期”。

See this example . 请参阅此示例


For something a little bit more generic, but probably more efficient than converting all your values TO_DATE , you might want to try that: 对于一些通用的东西,但可能比将所有值转换为TO_DATE更有效率,您可能想尝试一下:

-- the calendar is the key part of the query (see below)
with calendar as (
  select extract(month from sysdate + level) as theMonth,
         extract(day from sysdate + level) as theDay
    from DUAL connect by ROWNUM <= 8)
--                                 ^
--              adjust to the right number of days you are looking for
select card.* from card join calendar
  on expiremonth = theMonth and expireDay = theDay

The idea here is to simply build a calendar with all the upcoming days and then join your data table on that calendar. 这里的想法是简单地建立一个包含所有未来几天的日历,然后将数据表加入该日历。 See an example here . 在这里查看示例

Try using to_char(sysdate - interval '2' DAY,'ddmmyyyy') to convert to character type. 尝试使用to_char(sysdate - interval '2' DAY,'ddmmyyyy')转换为字符类型。 The date format('ddmmyyyy') will depend of the value of expiredate 日期格式('ddmmyyyy')将取决于expiredate的值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM