SQL/PLSQL:日期函数总结_20170822
2017-08-22 14:17
489 查看
首先是日期format 大小写意义不同! 大小写意义不同! 大小写意义不同!
日期 | 格式 | 含义 | 补充说明 |
世纪 | CC | 两位数字 | 例如:21 |
年 | y | 一位年 | 例如:7 |
yy | 两位年 | 例如:17 | |
yyy | 三位年 | 例如:017 | |
yyyy | 四位年 | 例如:2017 | |
月 | mm | 两位数字 | 两位数字 |
mon | 月份三位字符 | mon全小写 MON全大写 Mon首字母大写 | |
month | 月份英文全拼 | 同上 | |
日 | d | 本周中的第几天 | 周日是第一天 |
dd | 本月中的第几天 | 每月一号是第一天 | |
ddd | 本年中的第几天 | 每年一月一号是第一天 | |
dy | 星期几(按字符集) | 英文环境显示缩写 | |
day | 英文环境显示全拼 (day,DAY,Day) | ||
季度 | Q | 季度 | 一位数字 (1,2,3,4) |
时 | HH24 | 24时制 | 两位数字 |
HH12 | 12时制 | ||
AM or PM | 上午 下午 | 两位汉字或字母 | |
分 | mi | 60进制 | 0 ~ 59 |
秒 | ss |
1
SELECT SYSDATE as "当前日期",2
--1.年3
to_char(SYSDATE,'y') AS "一位年",4
to_char(SYSDATE,'yy')AS "两位年",5
to_char(SYSDATE,'yyy') AS "三位年",6
to_char(SYSDATE,'yyyy') AS "四位年",7
--2.月8
to_char(SYSDATE,'mm')AS "月份" ,--月份,两位数字9
to_char(SYSDATE,'mon') AS "月份(缩写)", --月份,如Jun10
to_char(SYSDATE,'month') AS "月份(全拼)", --月份,如JunJanuary11
--3.日12
to_char(SYSDATE,'d') AS "d 当周第几天", --一周中的第几天,一位数字,星期四=513
to_char(SYSDATE,'dd')AS "dd 当月第几天" , --一月中的第几天,两位数字,2月9日=914
to_char(SYSDATE,'ddd') AS "ddd 当年第几天", --一年中的第几天,三位数字,2月9日+一月31天=4015
--4.星期几16
to_char(SYSDATE,'dy') AS "dy 星期几(缩写)",17
to_char(SYSDATE,'day') AS "dy 星期几(全拼)", --跟字符集变化18
--第几周19
to_char(sysdate,'w') AS "这个月第几周", --取当前时间是一个月中的第几周(从1日开始算)20
to_char(sysdate,'ww') AS "今年第几周",--取当前时间是一年中的第几周(从1.1开始算)21
--季度22
to_char(SYSDATE,'q') AS "季度" --季度,一位数字23
FROM dual;
日期函数
1.add_months(date, n)给日期加减n个月。返回日期类型. n可以为负数
2.last_day(date) 返回日期中最后一天的日期
返回date月份的最后一天, 如果没有trunc(带时分秒)则是date的时分秒例2.1 找出每个月倒数第三天入职的员工1
SELECT * FROM EMP WHERE LAST_DAY(HIREDATE) - 2 = HIREDATE; --倒数第n天的 就减n-1
例2.2
1
SQL> select sysdate, last_day(sysdate), last_day(trunc(sysdate, 'month')) from dual;23
SYSDATE 本月最后一天 本月最后一天,无时分秒4
----------- ----------------- ------------------------------5
2017/8/21 1 2017/8/31 16:47:3 2017/8/31例2.3
1
select trunc(trunc(sysdate, 'MONTH') - 1, 'MONTH') first_day_last_month
2
--或者to_date(extract(year from sysdate) ||extract(month from sysdate) -1,'yyyymm')
3
,trunc(sysdate, 'MONTH') - 1 / 86400 last_moment_of_last_month
4
,trunc(sysdate, 'MONTH') first_day_cur_month
5
,last_day(trunc(sysdate, 'MONTH')) + 1 - 1 / 86400 last_day_cur_month
6
from dual;
3 months_between(晚,早) 月份差 晚 - 早 = 正数
1select ceil(months_between(sysdate,sysdate-365*2)) from dual;
4 next_day(date,day) 下一个星期几
其中英文环境下星期几支持的格式为:'DAY' = Monday ~ Sunday'DY' = Mon-Sun'D' = 1-7 (1为星期日!)例如:1
alter SESSION set NLS_DATE_LANGUAGE='SIMPLIFIED CHINESE'; --中文环境使用 : 星期日 ~ 星期一
2
select next_day(sysdate, '星期日') 下周日,
3
next_day(sysdate, 1) 下周日
4
from dual;
5
6
alter SESSION set NLS_DATE_LANGUAGE=AMERICAN ; --英文环境使用 : Sun ~ Mon 或者 Sunday ~ Monday
7
select next_day(sysdate,'Sun'), next_day(sysdate,'Sunday'),
8
next_day(sysdate, 1) 下周日
9
from dual;
10
11
/*
12
无论中文/英文环境 next_day(date,1) 都好使!
13
*/
5,round() 舍入到最接近的日期 )
1select sysdate2
,round(sysdate) 不加参数默认四舍五入到天3
,round(sysdate, 'day') 四舍五入到本周day --舍入到星期日 而不是星期一!!!4
,round(sysdate, 'month') 四舍五入到本月month5
,round(sysdate, 'year') 四舍五入本到year6
from dual;
6 trunc() 截断到最接近的日期,单位为天 ,返回的是日期类型
select sysdate ,trunc(sysdate) 截断当前日期 --返回当前日期,无时分秒 ,trunc(sysdate, 'day') 截断到本周day --返回当前星期的星期天,无时分秒 ,trunc(sysdate, 'month') 截断到本月1号month --返回当前月的1日,无时分秒 ,trunc(sysdate, 'year') 截断到year --返回当前年的1月1日,无时分秒from dual;其它日期函数
1.extract()
函数:从给定的日期中抽取出特定的部分 , 返回类型是numberSELECT EXTRACT ([YEAR] | [MONTH] | [DAY] | [HOUR] | [MINUTE] | [SECOND] ...还可以取出时间戳 不常用略了FROM [datetime_value_expression] |[interval_value_expression]);
2、tz_offset()
将命名地区形式的时区转换成时区的绝对偏移量select tz_offset('Asia/Shanghai'),tz_offset('Canada/Yukon')from dual;要得到合法时区名的列表,可以查询V$TIMEZONE_NAMES动态性能视图。SELECT * FROM V$TIMEZONE_NAMES;3、to_timestamp(char,'fmt')
将字符串以给定的日期格式模型转换成时间戳select to_timestamp('20071010 15:25:00','YYYYMMDD HH24:MI:SS')from dual;4、to_yminterval('year-month')
将字符串转成成年到月的间隔将雇员的入职日期加上1年2个月select hire_date,hire_date + to_yminterval('01-02')from employees;5、to_dsinterval('day hh:mi:ss') ※
将字符串转成成天到秒的间隔将雇员的入职日期加上100天10个小时select to_char(hire_date,'YYYYMMDD HH24:MI:SS'),to_char(hire_date + to_dsinterval('100 10:00:00'),'YYYYMMDD HH24:MI:SS')from employees;6.new_time() 不同时区的处理
用法: select new_time(date, timezone1, timezone2) from dual;功效: 把timezone1时区的日期转换为timezone2时区的日期例如:select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdatefrom dual;7,greatest()返回日期列表中最晚日期
select greatest('01-1月-04','04-1月-04','10-2月-04') from dual;时间 & 时区
概念:地球分24个时区,东西各12个。一个时区代表1个小时。时区值通常以绝对偏移量格式来表示:带正负号的小时:分钟。东时区为正的,西时区为负的。时区一旦确定了,日期时间函数的返回值就参照该时区来返回。
oracle中,时区分为客户端的和服务器的两种,分别设置。1.查看数据库,会话时区:SELECT DBTIMEZONE, --查看数据库所在时区 SESSIONTIMEZONE --查看会话所在时区 FROM DUAL;
DB所在时区 +00:00 -->意味着当前的数据库使用OS所设置的时区,它在本人的计算机上设置为PST
注意:设置客户端的时区使用会话参数:time_zoneDBA通过指定手工建库时CREATE DATABASE 语句的SET TIME_ZONE 子句来设置数据库的默认时区。如果省略,那么默认数据库时区是操作系统时区。如果操作系统的时区格式是oracle不支持的,那么就把数据库的时区设为0时区。官方推荐数据库的时区都使用0时区。ALTER SESSION语句不能改变数据库时区。
2.设置会话时区为西五区(美国东部时间)alter session set time_zone = '-05:00'; --绝对偏移量,负为西
3.设置本会话使用数据库的时区alter session set time_zone = DBTIMEZONE;
4.把时区设置成本地alter session set time_zone = local; --不同操作系统,可能不支持
5.时区设置成某地域的时区alter session set time_zone = 'American/New_York'; --不同操作系统,可能不支持ALTER DATABASE SET TIME_ZONE = 'PST'; --本地的时区设置为太平洋标准时间
6.获取时区的时差 tz_offset()select tz_offset('PST') from dual;
7.获取时区名select tzname,tzabbrev from v$timezone_names;
8.将时间从时区1转换到时区2new_time(date,time_zone1,time_zone2)
TIMESTAMP类型
是DATE数据类型的扩展,有3种:TIMESTAMP(n) 时间精确到秒的小数点后n位(四舍五入)TIMESTAMP(n) WITH TIME ZONE 带时区的时间戳
TIMESTAMP(n) WITH LOCAL TIME ZONE 带本地时区的时间戳
其中n:小数秒精度取值范围是0-9。默认是6(微秒 ms)
特别注意:最后一种带本地时间戳的timestamp类型的列,它的值在保存到表中时,会按照数据库的时区进行自动转换;当从表中把该类型的列值取出来时,有按照客户端的时区做自动转换。前两种时间戳不会做这样的转行简单说:保存时 => 按照DB服务器的时区存数(不变了)
取数时 => 按照客户端的时区做自动
例子:
1
--创建订单表
2
CREATE TABLE web_orders
3
( order_dateTIMESTAMP WITH TIME ZONE, --订货时间使用 带时区 的时间戳
4
delivery_time TIMESTAMP WITH local TIME ZONE--送货时间使用 带本地时区 的时间戳
5
);
6
7
--美国客户插入订单
8
INSERT INTO web_orders VALUES (current_date, current_timestamp + 2); COMMIT;
9
10
--国内的物流哥们查询,看到正确的时间(东八区的时间)
11
SELECT * FROM web_orders;
12
13
--美国客户查询。自动转到西五区的日期
14
SELECT * FROM web_orders;
时间戳有关函数:
函数名 | 含义 | 返回类型 |
localtimestamp | 会话当前的时间戳 | TIMESTAMP |
current_timestamp | 会话当前的时间戳+时区 | TIMESTAMP WITH TIME ZONE |
systimestamp | DB当前的时间戳+时区 | TIMESTAMP WITH TIME ZONE |
from_tz(timestamp,time_zone) | 将时间和时区合并,返回一个 | TIMESTAMP WITH TIME ZONE |
sys_extract_utc(x) | 将x的时区去掉转换成UTC的时间 | TIMESTAMP |
to_timestamp(x[,fmt]) | 将x转换为时间戳 | TIMESTAMP |
to_timestamp_tz(x[,fmt]) | 将x转换为时间戳+时区 | TIMESTAMP WITH TIME ZONE |
cast('22-8月-17' as timestamp) | 将串转成时间戳 | 三种都可以 |
时间间隔类型(略)
INTERVAL数据类型用来存储两个日期值之间的差值。有两类INTERVAL:INTERVAL YEAR(year_precision) TO MONTH
INTERVAL DAY(day_precision) TO SECOND(fractional_seconds_precision)
说明:
year_precision是YEAR字段的精度,取值范围0—9,默认为2.
day_precision 是DAY字段的最大值(取值范围0—9,默认为2. )
fractional_seconds_precision 是小数秒的精度,取值范围0—9,默认为6.
例子
1、使用年到月的间隔
1
create table warranty(2
prod_id number,产品编号3
warranty_tiem interval year(3) to month --担保时间,year(3) --年的部分最少有三位4
);5
注意间隔类型的字面量写法:ansi语法6
insert into warranty values(123,interval '8' month);7
SQL 错误: ORA01873: 间隔的前导精度太小8
insert into warranty values(456,interval '200' year); --必须指定年的精度有3位9
insert into warranty values(456,interval '200' year(3)); --正确写法1011
注意间隔类型的字面量写法,oracle简单语法:'年-月'12
insert into warranty values(789,'200-11'); --200年 零 11个月简单写法2、使用天到秒的间隔
1
create table lab(
2
exp_id number,
3
test_time interval day to second --day不指定精度默认位2 秒精度默认为6
4
);
5
实验123的测试时间是90天一次
6
insert into lab values(123,'90 00:00:00');
7
insert into lab values(456, interval '06 03:30:16' day to second);
8
select * from lab;
9
间隔类型的使用常用于日期的加减运算中
时间应用举例
0 显示数字的英文拼写:
select to_char( to_date(222,'J'),'Jsp') from dual ; --Two Hundred Twenty-Two
这个是oracle的特殊用法,也不常用,就是显示数字的英文读法就是固定这么用的,没有其他用法。不要钻这个牛角尖
1 设定语言环境
1
select id, active_date from table12
UNION3
select 1, TO_DATE(null) from dual;4
select to_char(sysdate, 'day') 星期几5
,to_char(sysdate, 'dy', 'NLS_DATE_LANGUAGE = American') 英文缩写6
,to_char(sysdate, 'day', 'NLS_DATE_LANGUAGE = American') 英文全拼7
from dual;
设置日期语言:
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
或者
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
时间为null的用法
1
select id, active_date from table1
2
UNION
3
select 1, TO_DATE(null) from dual;
注意要用TO_DATE(null)
计算时间差
注:oracle时间差是以天数为单位,所以换算成年月,日
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual //时间差-年
select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual //时间差-月
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual //时间差-天
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual //时间差-时
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual //时间差-分
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒
更新时间
注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-年
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual //改变时间-月
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-时
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-分
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-秒
计算今年总共有多少天
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual;
结果= 365闰年366天
查找2002-02-28至2002-02-01间除星期一和七的天数
1
网上方法:
2
select count(*)
3
from (select rownum - 1 rnum
4
from all_objects --> 不太稳吧老哥...
5
where rownum <= to_date('2002-02-28', 'yyyy-mm-dd') - to_date('2002-02-01','yyyy-mm-dd') + 1)
6
where to_char(to_date('2002-02-01', 'yyyy-mm-dd') + rnum - 1, 'D') not in ('7', '1');
7
8
我的方法:
9
select count(*)
10
from (select to_char(to_date('2002-02-01', 'yyyy-mm-dd') + level - 1, 'D') as xqj --取第一天的星期几开始迭代
11
from dual --> 很稳
12
connect by level <= to_date('2002-02-28', 'yyyy-mm-dd') - to_date('2002-02-01', 'yyyy-mm-dd') + 1)
13
where xqj not in (7, 1);
14
计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)
select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
d(mod(date2-date1, 365), 30)作为日.
和客户端有关的日期时间函数:3个
current_date current_timestamp localtimestamp
三个都返回客户端的当前日期和时间,区别在于值的数据类型不一样
sessiontimezone:该函数返回客户端的时区设置
查看系统各个时间函数:
select sessiontimezone ,
current_date ,
current_timestamp ,
localtimestamp
from dual; ---(注意三个时间函数的精度)
相关文章推荐
- SQL日期和时间函数总结
- SQL/PLSQL:行转列总结_20170822
- 日期函数相关的SQL总结datediff(),datepart()
- sql使用convert转化长日期为短日期的总结
- SQL 10 函数 3 日期时间函数 - 4 日期增减(Oracle)
- oracle trunc 函数处理日期格式,日期类型很有用的几个sql
- web报表工具FineReport常用函数的用法总结(日期和时间函数)
- T-SQL: 15 个与日期时间相关的精典语句函数
- Sql语句--日期函数用法
- MySQL 日期时间函数常用总结
- SQL中的自定义函数总结
- 生成日期列表的函数.sql
- ORACLE SQL 常用函数总结
- SQL中日期常用的函数
- oracle trunc 函数处理日期格式,日期类型很有用的几个sql
- PLSQL总结——18.动态SQL
- [sql server] 问题总结10---SQL 日期转换 日期推算 增加或是减少一年或是一天 非常值得收藏
- sql使用convert转化长日期为短日期的总结
- SQL“常用查询语句”、“常用日期查询方式”、“常用函数”整理
- sql中查询日期的函数