个人记事,留下点滴
技术
技术

jdk8新特性-亮瞎眼的lambda表达式


参考:
http://www.oracle.com/technetwork/articles/java/architect-lambdas-part1-2080972.html
http://www.oracle.com/technetwork/articles/java/architect-lambdas-part2-2081439.html
http://blog.csdn.net/goldenfish1919/article/details/22747375


jdk8之前,尤其是在写GUI程序的事件监听的时候,各种的匿名内部类,大把大把拖沓的代码,程序毫无美感可言!既然java中一切皆为对象,那么,就类似于某些动态语言一样,函数也可以当成是对象啊!代码块也可以当成是对象啊!随着函数式编程的概念越来越深入人心,java中CODE=OBJECT的这一天终于到来了!如果你认为lambda表达式仅仅是为了从语法上简化匿名内部类,那就太小看jdk8的lambda了!

下面我们就来看下lambda表达式是如何亮瞎你的眼的!

lambda的定义
Funda-men-tally, a lambda expression is just a shorter way of writing an implementation of a method for later execution.
(1)lambda是方法的实现
(2)lambda是延迟执行的
首先看一个用匿名内部类的例子:


public class Test1{ public static void main(String args[]){ Runnable r = new Runnable(){ public void run(){ System.out.println("hello,lambda!"); } }; r.run(); } }

要换成lambda是什么样的呢?


public class Test2{ public static void main(String args[]){ Runnable r = ()->System.out.println("hello,lambda"); r.run(); } }

原先要5行代码,现在换成了仅仅1行!
这他妈的得省多少代码啊!
有木有很兴奋啊!
下面还有更刺激的!
lambda是如何做到的呢?看一下反编译之后的字节码:


public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: invokedynamic #2, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; 5: astore_1 6: aload_1 7: invokeinterface #3, 1 // InterfaceMethod java/lang/Runnable.run:()V 12: return LineNumberTable: line 3: 0 line 4: 6 line 5: 12 }

注意:上面有一个叫做invokedynamic的指令。invokedynamic是从jdk7开始引入的,jdk8开始落地。
可以看出来lambda并不是语法糖,它不是像匿名内部类那样生成那种带有$的匿名类。
简单的说,这里只是定义了一个方法调用点,具体调用那个方法要到运行时才能决定,这就是前面所说的:延迟执行。
具体的细节请google:invokedynamic。


为了配合lambda,jdk8引入了一个新的定义叫做:函数式接口(Functional interfaces)
函数式接口:
it is an interface that requires exactly one method to be implemented in order to satisfy the requirements of the interface.
(1)是一个接口
(2)只有一个待实现的方法
因为jdk8开始,接口可以有default方法,所以,函数式接口也是可以有default方法的,但是,只能有一个未实现的方法。
与此对应,新引入了一个注解: @FunctionalInterface
这个注解只是起文档的作用,说明这个接口是函数式接口,编译器并不会使用这个注解来决定一个接口是不是函数式接口。
不管加不加@FunctionalInterface这个注解,下面的接口都是函数式接口:


interface Something { public String doit(Integer i); }

lambda的语法
A lambda in Java essentially consists of three parts: a parenthesized set of parameters, an arrow, and then a body,
which can either be a single expression or a block of Java code.
lambda包含3个部分:
– (1)括弧包起来的参数
– (2)一个箭头
– (3)方法体,可以是单个语句,也可以是语句块
参数可以写类型,也可以不写,jvm很智能的,它能自己推算出来
public class Test3{
public static void main(String… args) {
Comparator c = (String lhs, String rhs) -> lhs.compareTo(rhs);
int result = c.compare(“Hello”, “World”);
System.out.println(result);
}
}
方法可以有返回,也可以无返回,如果有多个语句,还要返回值,需要加上return
public class Test4{
public static void main(String… args) {
Comparator
c =(lhs, rhs) ->{
System.out.println(“I am comparing ” +lhs + ” to ” + rhs);
return lhs.compareTo(rhs);
};
int result = c.compare(“Hello”, “World”);
System.out.println(result);
}
}
一个很有意思的事情:
之前我们说Object是一切类的父类,然而在加入了lambda以后,这种大一统的局面将不复存在:
public class Test5{
public static void main(String args[]){
Object r = ()->System.out.println(“hello,lambda”);
}

}
编译报错:
Test5.java:3: error: incompatible types: Object is not a functional interface
Object r = ()->System.out.println(“hello,lambda”);
^
1 error
很显然,编译器会检查变量的引用类型里面是否真的是一个函数式接口。那么如何让这段代码通过编译呢?
只需要加一个强制类型转换就可以了:



public class Test6{ public static void main(String args[]){ Object r = (Runnable)()->System.out.println("hello,lambda"); } }

lambda的词法作用域
我们知道,在匿名内部类中:


class Hello { public Runnable r = new Runnable() { public void run() { System.out.println(this); System.out.println(toString()); } }; public String toString() { return "Hello's custom toString()"; } } public class InnerClassExamples { public static void main(String... args) { Hello h = new Hello(); h.r.run(); } } System.out.println(this);这里的this指的是匿名类,而非Hello类。 想要引用Hello类需要Hello.this这样: class Hello { public Runnable r = new Runnable() { public void run() { System.out.println(Hello.this); System.out.println(Hello.this.toString()); } }; }

这种做法非常的反人类反直觉!看上去很恶心!
下面我们就来看一下伟大的lambda是什么样子的:

class Hello{
  public Runnable r = () -> {
       System.out.println(this);
       System.out.println(toString());
  };

  public String toString() {
      return "Hello's custom toString()";
  }
}
public class Test7{
  public static void main(String args[]){
        Hello h = new Hello();
        h.r.run();
  }
}

输出:
Hello’s custom toString()
Hello’s custom toString()
System.out.println(this);这里的this指的是Hello,而非lambda表达式!
但是,如果我们想在lambda表达式中返回lambda本身该怎么做呢?
变量捕获
匿名内部类只能引用作用域外面的final的变量,在lambda中对这个限制做了削弱,只需要是“等价final”就可以,没必要用final关键字来标识。


public class Test8{ public static void main(String args[]){ String message = "Howdy, world!";//不需要是final的 Runnable r = () -> System.out.println(message);//这里也能访问 r.run(); } }

“等效final”的意思是:事实上的final,所以,一旦赋值也是不可以改变的!比如:

public class Test9{
  public static void main(String args[]){
    String message = "Howdy, world!";
    Runnable r = () -> System.out.println(message);
    r.run();
    message = "change it";
  }
}
Test9.java:4: error: local variables referenced from a lambda expression must be final or effectively final
            Runnable r = () -> System.out.println(message); 
                                                  ^ 

1 error
如果上面的内容看上去平淡无奇的话,真正的大杀器出现了:方法引用
我们有一个这样的类:

class Person {
  public String firstName;
  public String lastName;
  public int age;
}

现在我们要把多个Person对象进行排序,有时候是按照firstName来排,有时候是按照lastName或者是age来排,使用lambda可以这样来做:

class Person{
  public String firstName;
  public String lastName;
  public int age;
  public Person(String firstName, String lastName, int age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
  public String toString(){
    return firstName+","+lastName+","+age;
  }
}
public class Test10{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 41),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Neward", 19),
      new Person("Matthew", "Neward", 13)
    };
    //sort by firstName
    Arrays.sort(people, (lhs,rhs)->lhs.firstName.compareTo(rhs.firstName));
    for(Person p : people){
      System.out.println(p);
    }
  }
}

我们可以把Comparator抽取出来,变成是Person对象的成员变量:

class Person{
  public String firstName;
  public String lastName;
  public int age;
  public Person(String firstName, String lastName, int age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
  public String toString(){
    return firstName+","+lastName+","+age;
  }
  public final static Comparator<person> compareFirstName =
      (lhs, rhs) -> lhs.firstName.compareTo(rhs.firstName);

  public final static Comparator</person><person> compareLastName =
      (lhs, rhs) -> lhs.lastName.compareTo(rhs.lastName);

  public final static Comparator</person><person> compareAge =
      (lhs, rhs) -> lhs.age - rhs.age;
}
public class Test11{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 41),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Neward", 19),
      new Person("Matthew", "Neward", 13)
    };
    Arrays.sort(people, Person.compareFirstName);//这里直接引用lambda
    for(Person p : people){
      System.out.println(p);
    }
  }
}

能起到同样的作用,但是语法看上去很奇怪,因为之前我们都是创建一个满足Comparator签名的方法,然后直接调用,而非定义一个变量,
然后引用这个变量!所以,还有这么一种调用方法:

class Person{
  public String firstName;
  public String lastName;
  public int age;
  public Person(String firstName, String lastName, int age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
  public String toString(){
    return firstName+","+lastName+","+age;
  }
  public static int compareFirstName(Person lhs, Person rhs){
    return lhs.firstName.compareTo(rhs.firstName);
  } 
  public static int compareLastName(Person lhs, Person rhs){
       return lhs.lastName.compareTo(rhs.lastName);
  }
}
public class Test12{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 41),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Neward", 19),
      new Person("Matthew", "Neward", 13)
    };
    Arrays.sort(people, Person::compareFirstName);
    for(Person p : people){
      System.out.println(p);
    }
  }
}

看Person::compareFirstName这种调用方式,
如果是static方法使用:类名::方法名
如果是instance方法:instance::方法名
但是,上面的代码还是不是很美观,因为Person只是一个数据对象,它不应该的对外提供compareFirstName或者是compareLastName这样的方法,
我们需要的仅仅是根据某个字段排序而已!很幸运的是jdk的api帮我们做了这件事:

import java.util.*;
class Person{
  public String firstName;
  public String lastName;
  public int age;
  public Person(String firstName, String lastName, int age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
  public String getFirstName(){
    return this.firstName;
  }
  public String getLastName(){
    return this.lastName;
  }
  public String toString(){
    return firstName+","+lastName+","+age;
  }
}
public class Test13{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 41),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Neward", 19),
      new Person("Matthew", "Neward", 13)
    };
    Arrays.sort(people, Comparator.comparing(Person::getFirstName));
    for(Person p : people){
      System.out.println(p);
    }
  }
}
Arrays.sort(people, Comparator.comparing(Person::getFirstName));

这里调用了Comparator.comparing方法,
但是注意这里的Person::getFirstName,很显然getFirstName()并不是static的,这是jdk做了封装的缘故!
这样做就非常完美了!
假如我们的排序算法改为:先按照lastName,然后按照age排序呢?

public class Test15{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 10),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Naward", 19),
      new Person("Matthew", "Nmward", 13)
    };
    Collections.sort(Arrays.asList(people), (lhs, rhs)->{
      if(lhs.getLastName().equals(rhs.getLastName())){
        return lhs.getAge()-rhs.getAge();
      }else{
        return lhs.getLastName().compareTo(rhs.getLastName());
      }
    });
    for(Person p : people){
      System.out.println(p);
    }
  }
}

很显然,应该还有更好的实现方式:

public class Test16{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 10),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Naward", 19),
      new Person("Matthew", "Nmward", 13)
    };
    Collections.sort(Arrays.asList(people),Comparator.comparing(Person::getLastName).thenComparing(Person::getAge));
    for(Person p : people){
      System.out.println(p);
    }
  }
}
Comparator.comparing(Person::getLastName).thenComparing(Person::getAge):简直帅呆了! 

还有更多的诸如:andThen()这样的方法,可以查api。
虚方法扩展
因为接口可以有default方法,所以很多类库都重写了,加入了一些default的方法,比如:

interface Iterator<t> { 
  boolean hasNext(); 
  T next(); 
  void remove(); 
  void skip(int i) default { 
    for (; i > 0 && hasNext(); i--) next(); 
  } 
}  

skip(i)就是一个default方法,这样所有的Iterator的子类都具有了一个叫skip的方法!
但是,大家对default方法的争议还是比较大的,比如:

interface I1 {
  public default void print(){
    System.out.println("I1");
  }
  public void hello();
}
interface I2{
  public default void print(){
    System.out.println("I2");
  }
  public void world();
}
class Impl implements I1,I2{
  public void hello(){
  }
  public void world(){
  }
}

如果在Impl上调用print会怎样呢?这不就是传说中的多继承么?想知道结果的话,自己试一下就可以了,哈哈
Stream:
之前的文章已经有介绍,下面只据一些使用的例子:
过滤age>12的元素:

people
      .stream()
      .filter(it -> it.getAge() >= 21) ;
过滤age>12的元素,并输出:
people.stream()
      .filter((it) -> it.getAge() >= 21)
      .forEach((it) -> 
        System.out.println("Have a beer, " + it.getFirstName()));
jdk预定义的Predicate:
Predicate<person> drinkingAge = (it) -> it.getAge() >= 21;
Predicate</person><person> brown = (it) -> it.getLastName().equals("Brown");
people.stream()
      .filter(drinkingAge.and(brown))
      .forEach((it) ->System.out.println("Have a beer, " + it.getFirstName()));
map:
IntStream ages =
  people.stream()
    .mapToInt((it) -> it.getAge()); 
//sum:
int sum = people.stream()
        .mapToInt(Person::getAge)
        .sum();

重点说下reduce:

public class Test17{
        public static void main(String args[]){
                List<integer> values = Arrays.asList(1,2,3,4,5);
                int sum = values.stream().reduce(0, (l,r)->l+r);
                System.out.println(sum);
        }
}

reduce(0, (l,r)->l+r)的工作原理是:第一个参数0作为后面lambda表达式的左操作数,然后从stream中取出一个元素作为右操作数,
二者运算的结果作为下一次运算的左操作数,依次循环。
最后看一个好玩的例子:

class Person{
  public String firstName;
  public String lastName;
  public int age;
  public Person(String firstName, String lastName, int age){
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }
  public String getFirstName(){
    return this.firstName;
  }
  public String getLastName(){
    return this.lastName;
  }
  public int getAge(){
    return this.age;
  }
  public String toString(){
    return firstName+","+lastName+","+age;
  }
  public String toJson(){
    return "{"+
        "firstName:\""+firstName+"\","+
        "lastName:\""+lastName+"\","+
        "age:"+age +
        "}";
  }
}
public class Test18{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 10),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Naward", 19),
      new Person("Matthew", "Nmward", 13)
    };
    String json = Arrays.asList(people).stream().map(Person::toJson).reduce("[",(l,r)->l + (l.equals("[")?"":",") + r)+"]";
    System.out.println(json);
  }
}
输出结果: 
[{firstName:"Ted",lastName:"Neward",age:10},{firstName:"Charlotte",lastName:"Neward",age:41},{firstName:"Michael",lastName:"Naward",age:19},{firstName:"Matthew",lastName:"Nmward",age:13}] 

还可以这样:

public class Test19{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 10),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Naward", 19),
      new Person("Matthew", "Nmward", 13)
    };
    String joined = Arrays.asList(people).stream().map(Person::toJson).collect(Collectors.joining(", "));
        System.out.println("[" + joined + "]"); 
  }
}

更进一步:

public class Test20{
  public static void main(String args[]){
    Person people[] = new Person[]{
      new Person("Ted", "Neward", 10),
      new Person("Charlotte", "Neward", 41),
      new Person("Michael", "Naward", 19),
      new Person("Matthew", "Nmward", 13)
    };
    String json = Arrays.asList(people).stream().map(Person::toJson).collect(Collectors.joining(", ", "[", "]"));
    System.out.println(json);
  }
}

如果只能用一个字来形容,那就是perfect!

ORA-01830: 日期格式图片在转换整个输入字符串之前结束

1、错误原因:
date类型不能包含秒以后的精度。
如日期:2010-01-01 20:02:20.0

解决方法:将日期秒以后的精度去除
如日期:2010-01-01 20:02:20

2、INSERT INTO TEST2 (C1, C2,c3) VALUES (${v1},${v2},to_date(${v3},’yyyy-mm-dd’));
oracle里面不需要以“;”结尾。

3、修改数据库日期格式:
alter session set nls_date_format=’yyyy-mm-dd hh24:mi:ss’

这个命令的适用范围,是修改当前SESSION,另外这不能修改第三方工具的日期格式,如:PL/SQL DEVELOPER需要在Tools->Preferences->User Interface->Date/Time下修改格式即可,第三方工具的日期格式在工具内部自己去设置,我估计你也应该在第三方工具下才会看到这样的效果,一般默认情况下ORACLE默认的日期格式不是这样的。

在默认的sqlplus或者sqlplusw下或者程序编写过程中,执行该命令后,如果是同一个session是肯定会产生你要的效果。

如果要将整体的数据库级别默认格式改掉需要修改参数文件,并重启数据库才可以,但是这个也改不掉你第三方工具的显示格式,第三方工具只能在工具内部去改,它只能改掉默认的日期格式,第三方工具都是转换后的;但是很多时候容易被工具所忽悠,给人的感觉就是数据库就是这样存储的,其实存储的只有日期格式,没有YYYYMM这些东西,这些东西都是通过算法计算出来的结果,然后根据格式要求进行对应的格式化给看到的这样的效果而已。

4、INSERT INTO TEST2 (C1, C2,c3) VALUES (‘1’,1,to_date(‘2010-12-27 00:00:00′,’yyyy-mm-dd’)) 不可以
INSERT INTO TEST2 (C1, C2,c3) VALUES (1,1,to_date(‘2010-12-27 00:00:00′,’yyyy-mm-dd hh24:mi:ss’)) 可以
to_date是类型转换,不是格式转换,字符串和后面的格式要匹配;to_char才是转成对应格式;

oracle日期格式总结在oracle中处理日期大全

TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998

24小时格式下时间范围为: 0:00:00 – 23:59:59….
12小时格式下时间范围为: 1:00:00 – 12:59:59 ….
1.
日期和字符转换函数用法(to_date,to_char)

2.
select to_char( to_date(222,’J’),’Jsp’) from dual

显示Two Hundred Twenty-Two

3.
求某天是星期几
select to_char(to_date(‘2002-08-26′,’yyyy-mm-dd’),’day’) from dual;
星期一
select to_char(to_date(‘2002-08-26′,’yyyy-mm-dd’),’day’,’NLS_DATE_LANGUAGE = American’) from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE=’AMERICAN’;
也可以这样
TO_DATE (‘2002-08-26’, ‘YYYY-mm-dd’, ‘NLS_DATE_LANGUAGE = American’)

4.
两个日期间的天数
select floor(sysdate – to_date(‘20020405′,’yyyymmdd’)) from dual;

  1. 时间为null的用法
    select id, active_date from table1
    UNION
    select 1, TO_DATE(null) from dual;

注意要用TO_DATE(null)

6.
a_date between to_date(‘20011201′,’yyyymmdd’) and to_date(‘20011231′,’yyyymmdd’)
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: ’01-Jan-01′
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date(‘2002-08-26′,’yyyy-mm-dd’),’day’,’NLS_DATE_LANGUAGE = American’) from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS

8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum < = to_date(‘2002-02-28′,’yyyy-mm-dd’) – to_date(‘2002-
02-01′,’yyyy-mm-dd’)+1
)
where to_char( to_date(‘2002-02-01′,’yyyy-mm-dd’)+rnum-1, ‘D’ )
not
in ( ‘1’, ‘7’ )

查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).

9.
select months_between(to_date(’01-31-1999′,’MM-DD-YYYY’),
to_date(’12-31-1998′,’MM-DD-YYYY’)) “MONTHS” FROM DUAL;
1

select months_between(to_date(’02-01-1999′,’MM-DD-YYYY’),
to_date(’12-31-1998′,’MM-DD-YYYY’)) “MONTHS” FROM DUAL;

1.03225806451613
10. Next_day的用法
Next_day(date, day)

Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D

11
select to_char(sysdate,’hh:mi:ss’) TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;

select to_char(sys_date,’hh:mi:ss’) from all_objects;
12.
获得小时数

SELECT EXTRACT(HOUR FROM TIMESTAMP ‘2001-02-16 2:38:40′) from offer
SQL> select sysdate ,to_char(sysdate,’hh’) from dual;

SYSDATE TO_CHAR(SYSDATE,’HH’)


2003-10-13 19:35:21 07

SQL> select sysdate ,to_char(sysdate,’hh24′) from dual;

SYSDATE TO_CHAR(SYSDATE,’HH24′)


2003-10-13 19:35:21 19

获取年月日与此类似
13.
年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),
12 ) MONTHS,
newer_date,
older_date
from ( select hiredate older_date,
add_months(hiredate,rownum)+rownum newer_date
from emp )
)

14.
处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), ‘yyyymmdd’),last_day(sysdate) from dual

16.
找出今年的天数
select add_months(trunc(sysdate,’year’), 12) – trunc(sysdate,’year’) from dual

闰年的处理方法
to_char( last_day( to_date(’02’ || :year,’mmyyyy’) ), ‘dd’ )
如果是28就不是闰年

17.
yyyy与rrrr的区别
‘YYYY99 TO_C


yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001

18.不同时区的处理
select to_char( NEW_TIME( sysdate, ‘GMT’,’EST’), ‘dd/mm/yyyy hh:mi:ss’) ,sysdate
from dual;

19.
5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,’SSSSS’)/300) * 300,’SSSSS’) ,TO_CHAR(sysdate,’SSSSS’)
from dual

2002-11-1 9:55:00 35786
SSSSS表示5位秒数

20.
一年的第几天
select TO_CHAR(SYSDATE,’DDD’),sysdate from dual
310 2002-11-6 10:03:51

21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A24) Hours,
TRUNC(A
2460 – 60TRUNC(A24)) Minutes,
TRUNC(A
246060 – 60TRUNC(A2460)) Seconds,
TRUNC(A
246060100 – 100TRUNC(A2460*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) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六

oracle中有很多关于日期的函数

在oracle中有很多关于日期的函数,如:
1、add_months()用于从一个日期值增加或减少一些月份
date_value:=add_months(date_value,number_of_months)
例:
SQL> select add_months(sysdate,12) “Next Year” from dual;

Next Year

13-11月-04

SQL> select add_months(sysdate,112) “Last Year” from dual;

Last Year

13-3月 -13

SQL>

2、current_date()返回当前会放时区中的当前日期
date_value:=current_date
SQL> column sessiontimezone for a15
SQL> select sessiontimezone,current_date from dual;

SESSIONTIMEZONE CURRENT_DA


+08:00 13-11月-03

SQL> alter session set time_zone=’-11:00′
2 /

会话已更改。

SQL> select sessiontimezone,current_timestamp from dual;

SESSIONTIMEZONE CURRENT_TIMESTAMP


-11:00 12-11月-03 04.59.13.668000 下午 -11:
00

SQL>

3、current_timestamp()以timestamp with time zone数据类型返回当前会放时区中的当前日期
timestamp_with_time_zone_value:=current_timestamp([timestamp_precision])
SQL> column sessiontimezone for a15
SQL> column current_timestamp format a36
SQL> select sessiontimezone,current_timestamp from dual;

SESSIONTIMEZONE CURRENT_TIMESTAMP


+08:00 13-11月-03 11.56.28.160000 上午 +08:
00

SQL> alter session set time_zone=’-11:00′
2 /

会话已更改。

SQL> select sessiontimezone,current_timestamp from dual;

SESSIONTIMEZONE CURRENT_TIMESTAMP


-11:00 12-11月-03 04.58.00.243000 下午 -11:
00

SQL>

4、dbtimezone()返回时区
varchar_value:=dbtimezone
SQL> select dbtimezone from dual;

DBTIME

-07:00

SQL>

5、extract()找出日期或间隔值的字段值
date_value:=extract(date_field from [datetime_value|interval_value])
SQL> select extract(month from sysdate) “This Month” from dual;

This Month

11

SQL> select extract(year from add_months(sysdate,36)) “3 Years Out” from dual;

3 Years Out

2006

SQL>

6、last_day()返回包含了日期参数的月份的最后一天的日期
date_value:=last_day(date_value)
SQL> select last_day(date’2000-02-01′) “Leap Yr?” from dual;

Leap Yr?

29-2月 -00

SQL> select last_day(sysdate) “Last day of this month” from dual;

Last day o

30-11月-03

SQL>

7、localtimestamp()返回会话中的日期和时间
timestamp_value:=localtimestamp
SQL> column localtimestamp format a28
SQL> select localtimestamp from dual;

LOCALTIMESTAMP

13-11月-03 12.09.15.433000
下午

SQL> select localtimestamp,current_timestamp from dual;

LOCALTIMESTAMP CURRENT_TIMESTAMP


13-11月-03 12.09.31.006000 13-11月-03 12.09.31.006000 下午 +08:
下午 00

SQL> alter session set time_zone=’-11:00′;

会话已更改。

SQL> select localtimestamp,to_char(sysdate,’DD-MM-YYYY HH:MI:SS AM’) “SYSDATE” from dual;

LOCALTIMESTAMP SYSDATE


12-11月-03 05.11.31.259000 13-11-2003 12:11:31 下午
下午

SQL>

8、months_between()判断两个日期之间的月份数量
number_value:=months_between(date_value,date_value)
SQL> select months_between(sysdate,date’1971-05-18′) from dual;

MONTHS_BETWEEN(SYSDATE,DATE’1971-05-18′)

389.855143

SQL> select months_between(sysdate,date’2001-01-01′) from dual;

MONTHS_BETWEEN(SYSDATE,DATE’2001-01-01′)

34.4035409

SQL>

9、next_day()给定一个日期值,返回由第二个参数指出的日子第一次出现在的日期值(应返回相应日子的名称字符串)

與周相關日期函數

1.查询某周的第一天
select trunc(decode(ww, 53, to_date(yy || ‘3112’, ‘yyyyddmm’), to_date(yy || ‘-‘ || to_char(ww * 7), ‘yyyy-ddd’)), ‘d’) last_day
from (select substr(‘2004-32’, 1, 4) yy, to_number(substr(‘2004-32’, 6)) ww
from dual)

select trunc(to_date(substr(‘2003-01’,1,5)||to_char((to_number(substr(‘2003-01′,6)))*7),’yyyy-ddd’),’d’)-6 first_day from dual

select min(v_date) from
(select (to_date(‘200201′,’yyyymm’) + rownum) v_date
from all_tables
where rownum < 370)
where to_char(v_date,’yyyy-iw’) = ‘2002-49’

2.查询某周的最后一天
select trunc(decode(ww, 53, to_date(yy || ‘3112’, ‘yyyyddmm’), to_date(yy || ‘-‘ || to_char(ww * 7), ‘yyyy-ddd’)), ‘d’) – 6 first_day
from (select substr(‘2004-33’, 1, 4) yy, to_number(substr(‘2004-33’, 6)) ww
from dual)

select trunc(to_date(substr(‘2003-01’,1,5)||to_char((to_number(substr(‘2003-01′,6)))*7),’yyyy-ddd’),’d’) last_day from dual

select max(v_date) from
(select (to_date(‘200408′,’yyyymm’) + rownum) v_date
from all_tables
where rownum < 370)
where to_char(v_date,’yyyy-iw’) = ‘2004-33’

3.查询某周的日期
select min_date, to_char(min_date,’day’) day from
(select to_date(substr(‘2004-33′,1,4)||’001’+rownum-1,’yyyyddd’) min_date
from all_tables
where rownum <= decode(mod(to_number(substr(‘2004-33’,1,4)),4),0,366,365)
union

select to_date(substr(‘2004-33’,1,4)-1||
decode(mod(to_number(substr(‘2004-33′,1,4))-1,4),0,359,358)+rownum,’yyyyddd’) min_date
from all_tables
where rownum <= 7
union

select to_date(substr(‘2004-33′,1,4)+1||’001’+rownum-1,’yyyyddd’) min_date
from all_tables
where rownum <= 7
)
where to_char(min_date,’yyyy-iw’) =’2004-33′

oracle中时间运算

论坛中常常看到有对oracle中时间运算提问的问题,今天有时间,看了看以前各位兄弟的贴子,整理了一下,并作了个示例,希望会对大家有帮助。
首先感谢ern、eric.li及各版主还有热心的兄弟们

内容如下:
1、oracle支持对日期进行运算
2、日期运算时是以天为单位进行的
3、当需要以分秒等更小的单位算值时,按时间进制进行转换即可
4、进行时间进制转换时注意加括号(见示例中红色括号),否则会出问题

SQL> alter session set nls_date_format=’yyyy-mm-dd hh:mi:ss’;

会话已更改。

SQL> set serverout on
SQL> declare
2 DateValue date;
3 begin
4 select sysdate into DateValue from dual;
5 dbms_output.put_line(‘源时间:’||to_char(DateValue));
6 dbms_output.put_line(‘源时间减1天:’||to_char(DateValue-1));
7 dbms_output.put_line(‘源时间减1天1小时:’||to_char(DateValue-1-1/24));
8 dbms_output.put_line(‘源时间减1天1小时1分:’||to_char(DateValue-1-1/24-1/(2460)));
9 dbms_output.put_line(‘源时间减1天1小时1分1秒:’||to_char(DateValue-1-1/24-1/(24
60)-1/(24606
0)));
10 end;
11 /
源时间:2003-12-29 11:53:41
源时间减1天:2003-12-28 11:53:41
源时间减1天1小时:2003-12-28 10:53:41
源时间减1天1小时1分:2003-12-28 10:52:41
源时间减1天1小时1分1秒:2003-12-28 10:52:40

PL/SQL 过程已成功完成。

execute相关的一些常识

execute、executeUpdate、executeQuery三者的区别(及返回值)


  1. ResultSet executeQuery(String sql); 执行SQL查询,并返回ResultSet 对象。
  2. int executeUpdate(String sql); 可执行增,删,改,返回执行受到影响的行数。
  3. boolean execute(String sql); 可执行任何SQL语句,返回一个布尔值,表示是否返回ResultSet 。
  4. execute是executeQuery和executeUpdate的综合.

具体使用方法,大概如下所述

executeUpdate() 这是 PreparedStatement 接口中的方法

executeUpdate(String sql) 这是 PreparedStatement 从父接口 Statement 中继承过来的方法

executeUpdate() 中执行 SQL 语句需要在创建 PerparedStatement 时通过 Connection 的 prepareStatement(String sql) 方法中写出,因为 PerparedStatement 中的 SQL 语句数据库需要进行预编译和缓存,因此要在创建 PerparedStatement 对象时给出 SQL 语句。

而 executeUpdate(String sql) 是 Statement 中的方法,参数中的 SQL 语句只是提交给数据库去执行,并不需要预编译。

如果 SQL 语句中有 ? 占位符,那么在设置好占位符中的值后,必须使用 executeUpdate() 执行。而 executeUpdate(String sql) 只是提交一个 SQL 语句,且这个语句中不能带有 ? 占位符

executeUpdate(sql)的返回值是更新的条数


关于时间转换的代码

时间转换的相关代码

public static long dateToLong (String in) {
// 将日期转成毫秒 yyyy-MM-dd HH:mm:ss 2014-5
SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

// String systimeString =com.alipay.util.UtilDate.getDateFormatter();
java.util.Date date2;
Calendar cal = Calendar.getInstance();
try {
date2 = format.parse(in);
cal.setTime(date2);

} catch (ParseException e) {
e.printStackTrace();
}

return cal.getTimeInMillis();
}
// 将毫秒转成日期 yyyy-MM-dd HH:mm:ss 2014-5
public static String longToDate (long in) {
SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(in);

String dateString = format.format(calendar.getTime());
// System.out.println(“longToDate: long:”+ in +” date:”+ dateString);
return dateString;

}