阅读更多

1顶
0踩

编程语言

原创新闻 Java 8 的日期与时间问题解决方案

2017-12-06 16:58 by 副主编 jihong10102006 评论(0) 有12287人浏览

来源:Gitbook

作者:寒月

 

写在前面

 

日常的工作中,我们也许会遇到 “判断 Unix 时间是否为 0 点” 的问题。我们也许会构建以下代码:

 

boolean at0Clock(long unixTimeStamp) {
  return unixTimeStamp % 86400 == 0;
}

  我们做一个单元测试(使用 junit 单元测试框架):

 

@Test
void testAt0Clock() {
  Calendar calendar = Calendar.getInstance();

  //
  // 设置日期与时间 2017-11-11T00:00:00
  //
  calendar.set(Calendar.YEAR, 2017);
  calendar.set(Calendar.MONTH, 10);  // November
  calendar.set(Calendar.DATE, 11);
  calendar.set(Calendar.HOUR, 0);
  calendar.set(Calendar.MINUTE, 0);
  calendar.set(Calendar.SECOND, 0);
  calendar.set(Calendar.MILLISECOND, 0);

  Assert.assertEquals(true, Main.at0Clock(calendar.getTimeInMillis() / 1000));
}

 感兴趣的读者可以试一试,单元测试是否通过。无论通过与否,也请尝试执行以下代码:

 

void printTimeZone() {
  TimeZone timeZone = Calendar.getInstance().getTimeZone();
  System.out.println(timeZone.getID() + " " + timeZone.getDisplayName());
}

 作者位于上海,单元测试 testAt0Clock() 不通过,执行代码 printTimeZone() 的输出:

Asia/Shanghai 中国标准时间

 关于单元测试 testAt0Clock() 不通过的原因,我们有必要先了解若干基础的概念:“Unix 时间”、“时区”。

 

Unix 时间、时区

 

Unix 时间

 

Wikipedia 中关于 Unix 时间 定义为:

Unix time is a system for describing a point in time, defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, minus the number of leap seconds that have taken place since then.

 根据定义:Unix 时间表示自 1970-01-01T00:00:00Z(Z 即表示 UTC 时间,请参阅 ISO 8601)所经过的秒数,并且移除期间的 “闰秒”(例如:1998-12-31T23:59:60Z)。Unix 时间体系中,每天固定 86400 秒。

 

Java 中的 Unix 时间

Java 确保:每天 24 小时、每小时 60 分、每分钟 60 秒。

 

Java 中获取 “当前” 时间的方法,其底层实现,全部由 java.lang.System.currentTimeMillis() 提供自 UTC 1970-01-01T00:00:00 的毫秒数。java.lang.System.currentTimeMillis() 作为 native 方法,其实现与 JVM 所在的机器相关(通常使用 NTP 协议保持更新)。

 

本文中,我们将 java.lang.System.currentTimeMillis() 的返回值,称为毫秒级精度的 “Unix 时间”。

时区

时区作为地理概念,表示 “遵守统一时间标准的一个地区”。Wikipedia 中关于 时区 定义为:

A time zone is a region of the globe that observes a uniform standard time for legal, commercial, and social purposes.

 

使用与 UTC 的偏移来表示时区,例如:中国所在时区为 UTC+08:00(又称为 Chinese Standard Time,即 “中国标准时间”;tz 时区数据库 中,表示为 Asia/Shanghai)

 

“偏移”,即为表示与 UTC 的时间差。例如:1970-01-01T00:00:00Z == 1970-01-01T00:08:00+08:00(+08:00 表示位于 UTC+08:00 时区)。

 

关于 boolean at0Clock(long unixTimeStamp)

 

完成 “Unix 时间” 和 “时区” 的阅读,相信读者对于 boolean at0Clock(long unixTimeStamp) 的单元测试不通过的原因,已经有了自己的答案。

 

Calendar 的实现:首先,根据年、月、日、时、分、秒计算获得自 1970-01-01 00:00:00 经过的秒数;然后,减去当前时区的 UTC 偏移,得到 Unix 时间。因此,对于运行于 “中国标准时间” 的系统,正确的 >boolean at0Clock(long unixTimeStamp) 实现:

 

boolean at0Clock(long unixTimeStamp) {
  return (unixTimeStamp + 8 * 3600) % 86400 == 0;
}

 Java 8 以前的方案

 

承载日期与时间的类型

 

java.util.Date

 

使用 java.util.Date 表示日期与时间,其承载了毫秒级精度的 Unix 时间,除此之外的功能(包括:承载 “年、月、日、时、分、秒” 字段,格式化,字符串解析),均标记为 @Deprecated

 

java.util.Date 实现了 Comparable 接口,并提供 boolean before(Date) / boolean after(Date) 方法。

 

特别说明:java.util.DateString toString() 方法,使用系统的时区。

 

void printDate(java.util.Date date) {
  //
  // date 表示日期与时间,输出:
  //   1. Unix 时间(毫秒)
  //   2. EEE MMM dd HH:mm:ss zzz yyyy 格式输出
  //
  System.out.println(String.format("%d - %s", date.getTime(), date.toString()));
}

void usingDate() {
  java.util.Date now = new java.util.Date();  // 当前时间
  printDate(now);

  java.util.Date date = new java.util.Date(1511193600 * 1000L);  // Unix 时间:1511193600 * 1000(毫秒)
  printDate(date);  // 输出:1511193600000 - Tue Nov 21 00:00:00 CST 2017

  date.setTime(0 * 1000L);  // 设置时间,Unix 时间:0 * 1000(毫秒)
  printDate(date);  // 输出:0 - Thu Jan 01 08:00:00 CST 1970
}

 此外,Java 提供了 java.sql.Datejava.sql.Timejava.sql.Timestamp,作为 java.util.Date 的子类,用于 JDBC 中,分别代表 SQL 的 DATETIMETIMESTAMP 类型,其中 java.sql.Timestamp 的精度是纳秒。

 

java.util.Calendar

 

使用抽象类 java.util.Calendar 表示日期与时间,java.util.GregorianCalendar 是其常见的非抽象子类。

 

相比较于 java.util.Datejava.util.Calendar 除了承载毫秒级的 Unix 时间,还承载了时区信息(默认使用系统的时区),并且,提供了诸多接口:“年、月、日、时、分、秒” 字段的获取与设置,时区设置,日期与时间的偏移调整。

 

java.util.Calendar 实现了 Comparable 接口,并提供:boolean before(Object) / boolean after(Object) 方法。

 

void printCalendar(Calendar calendar) {
  //
  // date 表示时间和日期,输出:
  //   1. Unix 时间(毫秒)
  //   2. 格式化输出 yyyy-MM-dd HH:mm:ss
  //
  System.out.println(String.format("%d -> %04d-%02d-%02d %02d:%02d:%02d", calendar.getTime().getTime(),
    calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE),
    calendar.get(Calendar.HOUR), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)));
}

void usingCalendar() {
  Calendar calendar = Calendar.getInstance();  // 当前时间
  printCalendar(calendar);

  calendar.setTime(new Date(1511193600 * 1000L + 12));  // Unix 时间:1511193600 * 1000 + 12(毫秒)
  printCalendar(calendar);  // 输出:1511193600012 -> 2017-11-21 00:00:00

  //
  // 设置日期与时间 2017-10-31T00:00:00
  //
  calendar.set(2017, Calendar.OCTOBER, 31, 0, 0, 0);
  printCalendar(calendar);  // 输出:1509379200012 -> 2017-10-31 00:00:00

  //
  // 设置时区
  //
  calendar.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));
  printDate(calendar.getTime());  // 输出:1509379200012 - Tue Oct 31 00:00:00 CST 2017
  printCalendar(calendar);  // 输出:1509379200012 -> 2017-10-31 01:00:00

  calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
  printDate(calendar.getTime());  // 1509379200012 - Tue Oct 31 00:00:00 CST 2017

  calendar.set(Calendar.SECOND, 0);
  printDate(calendar.getTime());  // 1509382800012 - Tue Oct 31 01:00:00 CST 2017
  printCalendar(calendar);  // 1509382800012 -> 2017-10-31 01:00:00

  //
  // 设置 & 调整
  //
  calendar.add(Calendar.MINUTE, 60);
  printCalendar(calendar);  // 1509382800012 -> 2017-10-31 02:00:00

  calendar.roll(Calendar.DATE, 1);
  printCalendar(calendar);  // 1506794400012 -> 2017-10-01 02:00:00
}

 格式化输出 & 字符串解析

 

通过抽象类 java.text.DateFormat 及其非抽象子类 java.text.SimpleDateFormat,能够快速地进行日期与时间的格式化输出和字符串解析。关于日期与时间字段(年、月、日、时、分、秒、时区)格式化 & 解析的模式,请参阅 Java doc

 

void formatAndParse() throws ParseException {
  DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss XXX");  // XXX 即为 “时区”

  //
  // 格式化
  //
  Calendar calendar = Calendar.getInstance();
  calendar.setTime(new Date(0));
  System.out.println(dateFormat.format(calendar.getTime()));  // 输出:1970-01-01T08:00:00 +08:00

  //
  // 解析
  //
  String raw = "2017-11-30T00:00:00 +00:00";
  Date date = dateFormat.parse(raw);
  System.out.println(dateFormat.format(date));  // 输出:2017-11-30T08:00:00 +08:00
}

 可能存在的问题

 

概念定义:

 

  1. java.util.Date 仅承载 Unix 时间,与名称 “Date” 不相符
  2. 未区分 “Unix 时间” 与 “可理解的日期与时间”
  3. 缺少不携带时区信息的 “本地时间” 模型
  4. 未区分 “时区” & “UTC 偏移”
  5. 无 “时间段” 模型

 

编程模型:

 

  1. 承载日期与时间的类型,全部 “mutable”
  2. java.util.Calendar:月份表达范围 0-11
  3. java.text.DateFormat:非线程安全

 

更多的内容,请参考:Java 8 日期与时间方案(JSR 310)提案者的访谈

 

Java 8 的方案 (JSR 310)

 

承载日期与时间的类型

 

承载日期与时间的类型主要包括:java.time.Instantjava.time.LocalDate / java.time.LocalTime / java.time.LocalDateTimejava.time.ZonedDateTime,全部是 “immutable” 类型。

 

Instant

 

java.time.Instant 承载纳秒级精度的 Unix 时间,其 String toString() 方法基于 ISO-8601 进行格式化。Instant 不承载时区信息。

 

Instant now = Instant.now();
System.out.println(now);

Instant instant = Instant.ofEpochSecond(1511193600L);
System.out.println(instant);  // 输出:2017-11-20T16:00:00Z

instant = Instant.ofEpochMilli(15111936001206L);
System.out.println(instant);  // 输出:2448-11-16T16:00:01.206Z

instant = Instant.ofEpochSecond(1511193600L, 276);
System.out.println(instant);  // 输出:2017-11-20T16:00:00.000000276Z

 LocalDate / LocalTime / LocalDateTime

 

java.time.LocalDate 用于表示 “本地日期”,无 “时间”。LocalDate 不承载时区信息。

 

LocalDate now = LocalDate.now();  // 使用系统所在时区,由当前的 Unix 时间构建
System.out.println(now);

LocalDate date = LocalDate.of(2017, 11, 25);
System.out.println(date);  // 输出:2017-11-25

date = LocalDate.of(2017, Month.DECEMBER, 20);
System.out.println(date);  // 输出:2017-11-20

 java.time.LocalTime 用于表示 “本地时间”,无 “日期”。LocalTime 不承载时区信息。

 

 

LocalTime now = LocalTime.now();  // 使用系统所在时区,由当前的 Unix 时间构建
System.out.println(now);

LocalTime time = LocalTime.of(11, 20);
System.out.println(time);  // 输出:11:20

time = LocalTime.of(13, 20, 12);
System.out.println(time);  // 输出:13:20:12

time = LocalTime.of(13, 20, 12, 1);
System.out.println(time);  // 输出:13:20:12.000000001

 java.time.LocalDateTime 用于表示 “本地日期与时间”。LocalDateTime 不承载时区信息。

 

 

LocalDate 实例与 LocalTime 实例能够共同构建 LocalDateTime 实例,由 LocalDateTime 实例能够获取 LocalDate 实例与 LocalTime 实例。

 

LocalDateTime now = LocalDateTime.now();  // 使用系统所在时区,由当前的 Unix 时间构建
System.out.println(now);

LocalDateTime dateTime = LocalDateTime.of(2017,11,20,13,47);
System.out.println(dateTime);  // 输出:2017-11-20T13:47

dateTime = LocalDateTime.of(2017,11,20,13,47, 20);
System.out.println(dateTime);  // 输出:2017-11-20T13:47:20

dateTime = LocalDateTime.of(2017,11,20,13,47, 20, 1);
System.out.println(dateTime);  // 输出:2017-11-20T13:47:20.000000001

//
// LocalDate & LocalTime -> LocalDateTime
//
LocalDate date = LocalDate.of(2017, 11, 20);
LocalTime time = LocalTime.of(16, 32, 25, 6);

dateTime =  date.atTime(time);
System.out.println(dateTime);  // 输出:2017-11-20T16:32:25.000000006

dateTime = date.atTime(17,11,21);
System.out.println(dateTime);  // 输出:2017-11-20T17:11:21

dateTime = time.atDate(date);
System.out.println(dateTime);  // 输出:2017-11-20T16:32:25.000000006

//
// LocalDateTime -> LocalDate & LocalTime
//
dateTime = LocalDateTime.of(2017,11,20,13,47, 20, 1);

date = dateTime.toLocalDate();
System.out.println(date);

time = dateTime.toLocalTime();
System.out.println(time);

 由于 LocalDateTime 不承载时区信息,因此,其不能与 Instant 相互转换,必须提供时区信息。

 

 

LocalDateTime localDateTime = LocalDateTime.of(2017,11,25,13,6,7);
System.out.println(localDateTime);  // 输出:2017-11-30T14:56:07

Instant instant = localDateTime.toInstant(ZoneOffset.of("+08:00"));
System.out.println(instant);  // 输出:2017-11-25T05:06:07Z

LocalDateTime localDateTimeFromInstant = instant.atZone(ZoneId.of("Asia/Tokyo")).toLocalDateTime();
System.out.println(localDateTimeFromInstant);  // 输出:2017-11-25T14:06:07

LocalDateTime localDateTime = LocalDateTime.of(2017,11,30,14,56,7);
System.out.println(localDateTime);  // 输出:2017-11-30T14:56:07

 ZonedDateTime

 

java.time.ZonedDateTime 用于表示位于特定 “时区” 的 “日期与时间”,其 “时区” 信息使用 tz 时区数据库 表示(明确与 UTC 偏移区分)。

 

ZonedDateTime 的时区调整方法非常明确,区分:保持 “Unix 时间” 固定进行时区调整和保持 “本地日期与时间” 固定进行时区调整。 (相比较于 java.util.Calendar,更加清晰)

 

LocalDateTime localDateTime = LocalDateTime.of(2017, 11, 11,14,57,21);
System.out.println(localDateTime);  // 输出:2017-11-11T14:57:21

ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);  // 输出:2017-11-11T14:57:21+08:00[Asia/Shanghai]
System.out.println(zonedDateTime.toInstant().getEpochSecond());

zonedDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println(zonedDateTime);  // 输出:2017-11-11T15:57:21+09:00[Asia/Tokyo]
System.out.println(zonedDateTime.toInstant().getEpochSecond());

zonedDateTime = zonedDateTime.withZoneSameLocal(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);  // 输出:2017-11-11T15:57:21+09:00[Asia/Tokyo]
System.out.println(zonedDateTime.toInstant().getEpochSecond());

 java.time.OffsetDateTimejava.time.OffsetTime 使用相对于 UTC 的偏移承载 “时区” 信息,本文中不予展开阐述。

承载时间段的类型

 

承载时间段的类型主要包括:java.time.Periodjava.time.Duration,全部是 “immutable” 类型。

 

Period / Duration

 

java.time.Period 承载基于日期的时间段,例如:1 年 1 月 1 日。

 

Period period = Period.of(1, 1, 1);

LocalDate date = LocalDate.of(2017,11,12);
System.out.println(date);  // 输出:2017-11-12

date = date.plus(period);
System.out.println(date); // 输出:2018-12-13

LocalDate beginDate = LocalDate.of(2017, 11,12);
LocalDate endDate = LocalDate.of(2019, 12,11);

period = Period.between(beginDate, endDate);
System.out.println(period.getYears() + " years, " + period.getMonths() + " months, " + period.getDays() + " days");  // 2 years, 0 months, 29 days

 java.time.Duration 承载基于秒的时间段(提供纳秒级精度)。

 

 

Duration duration = Duration.ofSeconds(86401);

LocalDateTime dateTime = LocalDateTime.of(2017,11,12,0,0,0);
System.out.println(dateTime);  // 2017-11-12T00:00

dateTime = dateTime.minus(duration);
System.out.println(dateTime);  // 2017-11-10T23:59:59

LocalDateTime beginDateTime = LocalDateTime.of(2017, 11,12,0,0,0,12);
LocalDateTime endDateTime = LocalDateTime.of(2017, 11,12,0,1,1);
duration = Duration.between(beginDateTime, endDateTime);

System.out.println(duration.getSeconds() + " seconds, " + duration.getNano() + " nanos");  // 60 seconds, 999999988 nanos

 核心接口

 

TemporalTemporalAccessorTemporalAdjusterTemporalAmount

 

 

类图所示,java.time.temporal 提供的接口:

 

  1. TemporalField:日期与时间 “字段”,例如:2017-11-18 中的 18 “天”
  2. TemporalUnit:时间 “单位”,例如:1 年 13 天的 13 “天”
  3. TemporalAccessor:“时间相关” 对象的 “只读” 接口
  4. Temporal:“时间相关” 对象的 “读写” 接口,继承自 TemporalAccessor
  5. TemporalAdjusterTemporal 类型对象 “设置 & 调整” 的函数式接口
  6. TemporalAmount:时间段

java.time 提供的类:

 

  1. InstantLocalDateLocalTimeLocalDateTimeZonedDateTime:实现 TemporalTemporalAdjuster 接口
  2. DurationPeriod:实现 TemporalAmount 接口

 

 

//
// 调整日期与时间:通过 <code>Temporal</code> 接口
//
Duration duration = Duration.of(88, ChronoUnit.SECONDS);
localDateTime = localDateTime.plus(duration);
System.out.println(localDateTime);  // 输出:2017-11-30T14:57:35

//
// 调整日期与时间:通过 <code>Temporal</code> 接口
//
LocalDateTime nextDay = localDateTime.with(temporal -> temporal.plus(1, ChronoUnit.DAYS));
System.out.println(nextDay);  // 输出:2017-12-01T14:57:35

//
// 调整日期与时间:通过 <code>TemporalAdjuster</code> 接口
//
localDateTime = (LocalDateTime) nextDay.adjustInto(localDateTime);
System.out.println(localDateTime);  // 输出:2017-12-01T14:57:35

//
// 获取日期与时间字段值:通过 <code>TemporalAccessor</code> 接口
//
System.out.println("nextDay = " + nextDay.get(ChronoField.YEAR) + " 年 " + nextDay.get(ChronoField.MONTH_OF_YEAR) + " 月 " + nextDay.get(ChronoField.DAY_OF_MONTH) + " 日");
// 输出:nextDay = 2017 年 12 月 1 日

格式化输出 & 字符串解析

 

java.time.format.DateTimeFormatter 能够进行 TemporalAccessor 类型(包括:LocalDateLocalTimeLocalDateTimeZonedDateTime)的格式化输出。同时,LocalDateLocalTimeLocalDateTimeZonedDateTime 提供了静态的 parse 方法,能够进行字符串解析。

 

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy 年 MM 月 dd 日");

ZonedDateTime zonedDateTime = Instant.ofEpochSecond(1511463192L).atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(formatter.format(zonedDateTime));  // 输出:2017 年 11 月 24 日

LocalDate localDate = LocalDate.parse("2017 年 11 月 25 日", formatter);
System.out.println(localDate);  // 输出:2017-11-25

 LocalDateLocalTimeLocalDateTimeZonedDateTime 允许基于类型的默认格式进行格式化输出和字符串解析。

 

 

类型 默认格式示例
Instant 2017-11-23T10:15:30.00Z
LocalDate 2017-11-23
LocalTime 10:15:30
LocalDateTime 2017-11-23T10:15:30
ZonedDateTime 2017-11-23T10:15:30+01:00[Asia/Shanghai]

写在结束

 

通过本文的内容,期望读者能够对于日期与时间相关的概念能有基础的理解,也期望读者能够掌握 Java 提供的涉及日期与时间的类及接口。

来自: Gitbook
1
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 参数OPEN_CURSOR

    参考文章:http://www.itpub.net/thread-19466-1-1.htmlhttp://java.**.com/others/718640.html官方文档:B14237-04 OPEN_CURSORS s...

  • javascript基础学习系列七百三十二:设置游标方向

    在使用"prev"或"prevunique"打开游标时,每次调用continue()或advance()都会在对象存。openCursor()方法实际上可以接收两个参数,第一个是IDBKeyRange 的实例,第二个是表示方。通常,游标都是从对象存储的第一条记录开始,每次调用continue()或advance()都。注意,openCursor()的第一个参数是null,表示默认的键范围是所有值。createIndex()的第一个参数是索引的名称,第二个参数是索引属性的名称,第三个参数是包含。

  • oracle open_cursors参数配置

    oracle open_cursors参数配置 查看游标打开最大值设置 SQL&gt; show parameter open_cursors; oracle 默认open_cursors 为300 设置open_cursors值 alter system set open_cursors = 1000; alter system set open_cursors = 1000 scope = spfile; 若不带scope 对应默认scope为both 扩展了解 spfile参数的三种scope

  • oracle open游标,oracle open_cursors的含义及ORA-01000: 超出打开游标的最大数模拟

    PropertyDescriptionParameter typeIntegerDefault value50ModifiableALTER SYSTEMRange of values0 to 65535BasicYesOPEN_CURSORSspecifies the maximum number of open cursors (handles to private sql areas) a ...

  • 理解游标CURSOR,OPEN_CURSORS参数 以及视图V$OPEN_CURSOR, V$SESSION_CACHED_CURSOR

    游标概念:  游标的作用就是用于临时存储从数据库中提取的数据块,由系统或用户以变量的形式定义。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。 Cursor游标分两种,一种是Shared cursor,位于SGA的一种library cache object,通常我们所说的

  • Oracle的打开游标(OPEN_CURSORS)

    对oracle来说,什么是打开的游标查看v$open_cursor定义= kgllkhdl可以看到v$open_cursor的基础是x$kgllk,这个一个关于Libraray Cache Lock的视图。也就是说,只要SQL上持有了Libraray Cache Lock,它就是一个打开的游标。由此可见,被缓存的游标并不是越多越好,过多缓存游标会占用大量的共享池空间,严重时会导致ORA-4031问题,关于ORA-4031报错,我们会在下一章节剖析。

  • SQL——游标

    深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

  • oracle opencursor,Oracle 的客户端应用如果使用了Open Cursor的机制,会导致在同一个会话(session)的重复的sql指令不能被Guardium记录...

    ProblemOracle 的客户端应用如果使用了Open Cursor的机制,会导致在同一个会话的重复的sql指令不能被Guardium记录。SymptomOracle的客户端应用如果使用了Open Cursor的机制,会导致在同一个会话的重复的sql指令不能被Guardium记录举个例子:以下三条sql指令在一个会话中执行:• 1. select * from A; -&gt; Oracle ...

  • open cursor for

    oracle中open cursor for 和for cursor in的区别如下:open cursor for 是直接打开游标查询结果,适用于单表查询,结果集一般不会太大。for cursor in是从大量数据中循环获取满足条件的记录,放入游标1、open cursor for 用法:CREATE OR REPLACE PROCEDURE AMLS.TEST(C_RES OUT SYS_RE

  • ABAP Using a Cursor to Read Data

    ABAP Using a Cursor to Read Data

  • 修改oracle open_cur,【学习笔记】oracle 11g新特性SQL Performance Analyzer使用案例教程...

    天萃荷净oracle研究中心学习笔记:分享一篇关于oracle 11g新特性的使用文章,详细介绍了oracle SQL Performance Analyzer优化器的使用案例教程。通过 SPA,您可以根据各种更改类型(如初始化参数更改、优化器统计刷新和数据库升级)播放特定的SQL 或整个 SQL 负载,然后生成比较报告,帮助您评估它们的影响.在 Oracle Database 11g 之前的版本...

  • Oracle Cursor的使用

    When Oracle Database executes a SQL statement, it stores the result set and processing information in an unnamedprivate SQL area. A pointer to this unnamed area, called acursor, lets youretrieve the

  • Oracle 关于V$OPEN_CURSOR

    参考链接:http://www.askmaclean.com/archives/about-dynamic-view-open_cursor.html#wrap 在之前的一次讨论中,有同行指出V$OPEN_CURSOR中列出的不是OPEN CURSOR而是SESSION CACHED CURSOR,原因是在一次ORA-01000(maximum open cursors exceeded)事故中...

  • Oracle快速入门(游标,抛出自定义异常信息,存储过程)

    一、游标: (1)游标的概念: 是用来操作查询结果集的,相当于JDBC中的Result (2)对应代码 select * from emp; 查询emp表

  • 用动态sql生成cursor

    有个学生提问 G3 2015-01-15 13:23:27 for list_init in (select PROV_CODE,PROV_NAME from province) loop insert into T_BUSI_MONTH_REPORT (PROV_CODE, PROV_NAME, BUSI_MONTH, BUSI_DAY, BUSI_TYPE, INSERTTIME

  • 修改oracle open_cur,ORACLE 判断OPEN_CURSOR参数设置合理性

    SID----------9SQL&gt;selectsidfromv$mystatwhererownum=1;SID----------9SessionMonitor:SQL&gt;selectSID,USER_NAME,SQL_TEXTfromv$open_cursorwheresid=9;SIDUSER_NAMESQL_TEXT-------------...

  • 重庆思庄技术分享——Oracle 参数 OPEN_CURSORS

    假设会话未打开OPEN_CURSORS指定的游标数,则将此值设置为高于实际需要的值不会增加开销。Oracle OPEN_CURSORS 参数是控制Oracle的数据库最大的游标数量,如果游标数量超出了 OPEN_CURSORS设定的值,则会出现ORA-01000: 错误消息:游标数过多。正确设置Oracle的OPEN_CURSORS参数需要考虑用户数量,SESSION数量,数据库会话之间共享游标的最小值,以及在应用程序中循环遍历游标所需要的操作。Oracle 参数 OPEN_CURSORS。

Global site tag (gtag.js) - Google Analytics