Working with Dates in PL/SQL(PL/SQL中使用日期)
Working with Dates in PL/SQL
By Steven Feuerstein
史蒂芬.佛伊尔斯坦
The previous articles in this introductory PL/SQL series focused on working with strings and numbers in PL/SQL-based applications. Without a doubt, strings and numbers are important, but it is certainly a very rare application that does not also rely on dates. You need to keep track of when events occurred, when people were born, and much more.
As a result, you will quite often need to
Declare variables and constants for dates
Use built-in functions to display and modify date values
Perform computations on dates
A date is also a considerably more complex datatype than a string or a number. It has multiple parts (year, month, day, hour, and so on), and there are many rules about what constitutes a valid date. This article gives you all the information you need in order to begin working with dates in your PL/SQL programs.
Dates, Time Stamps, and Intervals in PL/SQL
Most applications require the storage and manipulation of dates and times. Unlike strings and numbers, dates are quite complicated: not only are they highly formatted data, but there are also many rules for determining valid values and valid calculations (leap days and years, daylight saving time changes, national and company holidays, date ranges, and so on).
Fortunately, Oracle Database and PL/SQL provide a set of true date and time datatypes that store both date and time information in a standard internal format, and they also have an extensive set of built-in functions for manipulating the date and time.
There are three datatypes you can use to work with dates and times:
DATE—This datatype stores a date and a time, resolved to the second. It does not include the time zone. DATE is the oldest and most commonly used datatype for working with dates in Oracle applications.
TIMESTAMP—Time stamps are similar to dates, but with these two key distinctions: (1) you can store and manipulate times resolved to the nearest billionth of a second (9 decimal places of precision), and (2) you can associate a time zone with a time stamp, and Oracle Database will take that time zone into account when manipulating the time stamp.
INTERVAL—Whereas DATE and TIMESTAMP record a specific point in time, INTERVAL records and computes a time duration. You can specify an interval in terms of years and months, or days and seconds.
Listing 1 includes example variables whose declaration is based on these datatypes.
Code Listing 1: Declaring DATE, TIMESTAMP, and INTERVAL variables
DECLARE
l_today_date DATE := SYSDATE;
l_today_timestamp TIMESTAMP := SYSTIMESTAMP;
l_today_timetzone TIMESTAMP WITH TIME ZONE := SYSTIMESTAMP;
l_interval1 INTERVAL YEAR (4) TO MONTH := '2011-11';
l_interval2 INTERVAL DAY (2) TO SECOND := '15 00:30:44';
BEGIN
null;
END;
Working with intervals and time stamps with time zones can be very complicated; relatively few developers will need these more advanced features. This article focuses on the core DATE and TIMESTAMP types, along with the most commonly used built-in functions.
Choosing a datatype. With such an abundance of riches, how do you decide which of these date-and-time datatypes to use? Here are some guidelines:
Use one of the TIMESTAMP types if you need to track time down to a fraction of a second.
You can, in general, use TIMESTAMP in place of DATE. A time stamp that does not contain subsecond precision takes up 7 bytes of storage, just as a DATE datatype does. When your time stamp does contain subsecond data, it takes up 11 bytes of storage.
Use TIMESTAMP WITH TIME ZONE if you need to keep track of the session time zone in which the data was entered.
Use TIMESTAMP WITH LOCAL TIME ZONE if you want the database to automatically convert a time between the database and session time zones.
Use DATE when it’s necessary to maintain compatibility with an existing application written before any of the TIMESTAMP datatypes were introduced.
Use datatypes in your PL/SQL code that correspond to, or are at least compatible with, the underlying database tables. Think twice, for example, before reading a TIMESTAMP value from a table into a DATE variable, because you might lose information (in this case, the fractional seconds and perhaps the time zone).
Getting the current date and time. PL/SQL developers often need to retrieve and work with the current date and time. Most developers use the classic SYSDATE function, but Oracle Database now offers several functions to provide variations of this information, as shown in Table 1.
| Function | Time Zone | Datatype Returned |
| CURRENT_DATE | Session | DATE |
| CURRENT_TIMESTAMP | Session | TIMESTAMP WITH TIME ZONE |
| LOCALTIMESTAMP | Session | TIMESTAMP |
| SYSDATE | Database server | DATE |
| SYSTIMESTAMP | Database server | TIMESTAMP WITH TIME ZONE |
Table 1: SYSDATE and other options for working with the current date and time
Listing 2 displays the values returned by calls to SYSDATE and SYSTIMESTAMP.
Code Listing 2: Calls to SYSDATE and SYSTIMESTAMP and the returned values
BEGIN
DBMS_OUTPUT.put_line (SYSDATE);
DBMS_OUTPUT.put_line (SYSTIMESTAMP);
DBMS_OUTPUT.put_line (SYSDATE - SYSTIMESTAMP);
END;
/
Here is the output:
07-AUG-11
07-AUG-11 08.46.16.379000000 AM -05:00
-000000000 00:00:00.379000000
Because I have passed dates and time stamps to DBMS_OUTPUT.PUT_LINE, Oracle Database implicitly converts them to strings, using the default format masks for the database or the session (as specified by the National Language Settings NLS_DATE_FORMAT parameter). A default installation of Oracle Database sets the default DATE format to DD-MON-YYYY. The default TIMESTAMP format includes both the date offset and the time zone offset.
Note that it is possible to perform date arithmetic: I subtract the value returned by SYSTIMESTAMP from the value returned by SYSDATE. The result is an interval that is very close (but not quite equal) to zero.
Converting dates to strings and strings to dates. As with TO_CHAR for numbers, you use another version of the TO_CHAR function to convert a date or a time stamp to a string. And, again as with numbers, Oracle Database offers a large set of format elements to help you tweak that string so it appears exactly as you need it. Here are some examples:
Use TO_CHAR without a format mask. If you do not include a format mask, the string returned by TO_CHAR will be the same as that returned when Oracle Database performs an implicit conversion:
BEGIN
DBMS_OUTPUT.put_line (
TO_CHAR (SYSDATE));
DBMS_OUTPUT.put_line (
TO_CHAR (SYSTIMESTAMP));
END;
/
07-AUG-11
07-AUG-11 08.55.00.470000000 AM -05:00Use TO_CHAR to display the full names of both the day and the month in the date:
BEGIN
DBMS_OUTPUT.put_line (
TO_CHAR (SYSDATE,
'Day, DDth Month YYYY'));
END;
/
Sunday , 07TH August 2011Note: The language used to display these names is determined by the NLS_DATE_LANGUAGE setting, which can also be specified as the third argument in the call to TO_CHAR, as in
BEGIN
DBMS_OUTPUT.put_line (
TO_CHAR (SYSDATE,
'Day, DDth Month YYYY',
'NLS_DATE_LANGUAGE=Spanish'));
END;
/
Domingo , 07TH Agosto 2011- Use TO_CHAR to display the full names of both the day and the month in the date—but without all those extra spaces in the date-as-string. Oracle Database, by default, pads the string with spaces to match the maximum length of the day or the month. In most situations, you don’t want to include that extra text, and Oracle Database offers a format element modifier, FM, to control blank and zero padding. In the following block, I prefix the format mask with FM and remove the 0 (before 7) and extra spaces after August:
BEGIN
DBMS_OUTPUT.put_line (
TO_CHAR (SYSDATE,
'FMDay, DDth Month YYYY'));
END;
/
Sunday, 7TH August 2011
You can also use the format mask to extract just a portion of, or information about, the date, as shown in the following examples:
What quarter is it?
TO_CHAR (SYSDATE, 'Q')
- What is the day of the year (1-366) for today’s date?
TO_CHAR (SYSDATE, 'DDD')
- What are the date and time of a DATE variable? (This is a very common requirement, because the default format mask for a date does not include the time component, which means that asking DBMS_OUTPUT.PUT_LINE to display a date leaves out the time.)
BEGIN
DBMS_OUTPUT.put_line (
TO_CHAR (SYSDATE,
'YYYY-MM-DD HH24:MI:SS'));
END;
/
You can also use EXTRACT to extract and return the value of a specified element of a date. For example
- What year is it?
EXTRACT (YEAR FROM SYSDATE)
- What is the day for today’s date?
EXTRACT (DAY FROM SYSDATE)
To convert a string to a date, use the TO_DATE or the TO_TIMESTAMP built-in function. Provide the string and Oracle Database returns a date or a time stamp, using the default format mask for the session:
DECLARE
l_date DATE;
BEGIN
l_date := TO_DATE ('12-JAN-2011');
END ;
If the string you provide does not match the default format, Oracle Database will raise an exception:
DECLARE
l_date DATE;
BEGIN
l_date := TO_DATE ('January 12 2011');
END;
/ ORA-01858: a non-numeric character was
found where a numeric was expected
You should not assume that the literal value you provide in your call to TO_DATE matches the default format. What if the format changes over time? Instead, always provide a format mask when converting strings to dates, as in
l_date := TO_DATE ('January 12 2011',
'Month DD YYYY');
Date truncation. Use the TRUNC built-in function to truncate a date to the specified unit of measure. The most common use of TRUNC is TRUNC (date)—without any format mask specified. In this case, TRUNC simply sets the time to 00:00:00. You can also use TRUNC to easily obtain the first day in a specified period. Here are some TRUNC examples:
Set l_date to today’s date, but with the time set to 00:00:00:
l_date := TRUNC (SYSDATE);
- Get the first day of the month for the specified date:
l_date := TRUNC (SYSDATE, 'MM');
- Get the first day of the quarter for the specified date:
l_date := TRUNC (SYSDATE, 'Q');
- Get the first day of the year for the specified date:
l_date := TRUNC (SYSDATE, 'Y');
Date arithmetic. Oracle Database enables you to perform arithmetic operations on dates and time stamps in several ways:
Add a numeric value to or subtract it from a date, as in SYSDATE + 7; Oracle Database treats the number as the number of days.
Add one date to or subtract it from another, as in l_hiredate - SYSDATE.
Use a built-in function to “move” a date by a specified number of months or to another date in a week.
Here are some examples of date arithmetic with a date and a number (assume in all cases that the l_date variable has been declared as DATE):
Set a local variable to tomorrow’s date:
l_date := SYSDATE + 1;
- Move back one hour:
l_date := SYSDATE - 1/24;
- Move ahead 10 seconds:
l_date := SYSDATE + 10 / (60 * 60 * 24);
When you add one date to or subtract it from another, the result is the number of days between the two. As a result, executing this block:
DECLARE
l_date1 DATE := SYSDATE;
l_date2 DATE := SYSDATE + 10;
BEGIN
DBMS_OUTPUT.put_line (
l_date2 - l_date1);
DBMS_OUTPUT.put_line (
l_date1 - l_date2);
END;
returns the following output:
10
-10
And the following function can be used to compute the age of a person, assuming that the person’s correct birth date is passed as the function’s only argument:
CREATE OR REPLACE FUNCTION
your_age (birthdate_in IN DATE)
RETURN NUMBER
IS
BEGIN
RETURN SYSDATE -
birthdate_in;
END your_age;
Oracle Database offers several built-in functions for shifting a date by the requested amount or finding a date:
ADD_MONTHS—adds the specified number of months to or subtracts it from a date (or a time stamp)
NEXT_DAY—returns the date of the first weekday named in the call to the function
LAST_DAY—returns the date of the last day of the month of the specified date
Here are some examples that use these built-in functions:
Move ahead one month:
l_date := ADD_MONTHS (SYSDATE, 1);
Move backward three months:
l_date := ADD_MONTHS (SYSDATE, -3);
- Starting with the last day of January, move ahead one month. Starting from a different date, go back one month. Starting with the last day of February, go back one month. Listing 3 shows three different calls to the ADD_MONTHS function along with the results. Code Listing 3: Calls to ADD_MONTHS
BEGIN
DBMS_OUTPUT.put_line (
ADD_MONTHS (TO_DATE ('31-jan-2011', 'DD-MON-YYYY'), 1));
DBMS_OUTPUT.put_line (
ADD_MONTHS (TO_DATE ('27-feb-2011', 'DD-MON-YYYY'), -1));
DBMS_OUTPUT.put_line (
ADD_MONTHS (TO_DATE ('28-feb-2011', 'DD-MON-YYYY'), -1));
END;Here is the output:
28-FEB-11
27-JAN-11
31-JAN-11You might be surprised at the third date in Listing 3. The first date (28 February) makes perfect sense. There is no 31st day in February, so Oracle Database returns the last day of the month. The second call to ADD_MONTHS moves the date from 27 February to 27 January: exactly one month’s change. But in the third call to ADD_MONTHS, Oracle Database notices that 28 February is the last day of the month, so it returns the last day of the month specified by the second argument.
Find the next Saturday after today’s date:
l_date := NEXT_DAY (SYSDATE, 'SAT');
-- or
l_date := NEXT_DAY (SYSDATE, 'SATURDAY');
The second argument must be a day of the week in the date language of your session (specified by NLS_DATE_LANGUAGE), provided as either the full name or the abbreviation. The returned date has the same time component as the date.
-------------------------------
present by dylan.
Working with Dates in PL/SQL(PL/SQL中使用日期)的更多相关文章
- 【SQL Server】中的日期函数和日期数据类型
SQL Server Date 函数 SQL Server的重要日期函数包括: 函数 描述 参数含义 GETDATE() 返回当前的日期和时间 DATEPART(datepart,date) 返 ...
- pl/sql和sql的区别
源地址:https://zhidao.baidu.com/question/187511430.html 1 sql(数据定义语言) 和PL/Sql的区别:答:SQL是结构化查询语言,比较接近自然语言 ...
- PL/SQL --> 动态SQL调用包中函数或过程
动态SQL主要是用于针对不同的条件或查询任务来生成不同的SQL语句.最常用的方法是直接使用EXECUTE IMMEDIATE来执行动态SQL语句字符串或字符串变量.但是对于系统自定义的包或用户自定的包 ...
- PL/SQL将sql脚本数据导入Oracle
PL/SQL将sql脚本数据导入数据库: 1.首先,使用plsql登录到需要导入数据的数据库.在[tools]--[Import tables] 2.选择第二个[SQL Inserts],在下面,点击 ...
- SQL PL/SQL语法手册
SQL PL/SQL语法手册 目 录 第一部分 SQL语法部分 3 一. CREATE TABLE 语句 3 二. CREATE SEQUENCE语句 5 三. CREATE VIEW语句 6 ...
- oracle中的sql%rowcount,sql%found、sql%notfound、sql%rowcount和sql%isopen
Oracle 存储过程 删除表记录时删除不存在的记录也是显示删除成功 create or replace procedure delDept(p_deptno in dept.deptno%type ...
- 转://使用showplan.sql分析sql Performance
在HelloDBA网站找到一个分析sql性能的工具—showplan,记录一下 showplan.sql下载路径:http://www.HelloDBA.com/Download/showplan.z ...
- [转载]Oracle数据库 sql%found,sql%notfound,sql%rowcount
sql%found,sql%notfound,sql%rowcount 在执行DML(insert,update,delete)语句时,可以用到以下三个隐式游标(游标是维护查询结果的内存中的一个区域, ...
- sql%found sql%notfound sql%rowcount sql%isopen
原文引入:http://blog.csdn.net/mh942408056/article/details/6949325 sql%found sql%notfound sql%rowcount sq ...
- [转载]SQL语句中的日期计算
1. 本月的第一天SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) 2. 本月的最后一天SELECT dateadd(ms,-3,DATEADD( ...
随机推荐
- [转帖]查看mysql分区名和各分区数据量
– 查看mysql分区名和各分区数据量 SELECT table_name, partition_name, table_rows FROM information_schema.PARTITIONS ...
- [转帖]PG-用户|角色管理
https://www.cnblogs.com/binliubiao/p/14415203.html 1. 角色 决定发起连接的命令的初始访问权限.在PG中,角色和用户相当于是一样的对象.区别在于 ...
- Oracle PDB的相关使用说明
Oracle PDB的相关使用说明 摘要 PDB pluggable database 是Oracle12c以上的版本(Oracle18c.oracle19c) 新增加的一个特性. 他可以实现灵活插拔 ...
- 一次w3wp出现crash的简单解决方案
1. 前几天同事求助, 说一台服务器iis出现多次崩溃的现象,重启iis就可以了. 具体原因不明. 之前遇到过类似的问题 感觉最彻底的解决方案是 抓dump然后使用windbg 进行分析. 但是自 ...
- vue3动态路由的addRoute和removeRoute使用
为什么需要有动态路由 有些时候,我们不同的身份角色,我们希望可以展示不同的菜单. 比如说:普通用户只有展示A菜单,管理员有A,B,C菜单 这个时候,我们就需要动态路由了! Vue2和vue3的区别 V ...
- 【scikit-learn基础】--『回归模型评估』之可视化评估
在scikit-learn中,回归模型的可视化评估是一个重要环节.它帮助我们理解模型的性能,分析模型的预测能力,以及检查模型是否存在潜在的问题.通过可视化评估,我们可以更直观地了解回归模型的效果,而不 ...
- chaincode中使用第三方库
本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处. 在fabric的chaincode开发时,有时候需要用到第三方库提供的功能.这 ...
- css自适应各种格式背景图
body { position: relative; background-color: #eee; background-image: url(链接); background-size: 100%; ...
- vs版本与version(内部版本号)的关系表table
为什么要查vs版本与内部verion的对应关系? 因为c++的项目需要对应的vs版本,给大型的c++项目升级vs版本是个耗时的工程,所以一般情况下开发者都会安装多个版本的vs. 对于sln文件,以文本 ...
- 关于git pull机制和游戏开发热更新思考
前言 今天由于网速很慢,在git pull更新时我观看了git pull的日志,让我联想到和我现在从事的游戏开发中的热更热有一定的相似性,把思绪记录下来. git pull 日志 使用tortoi ...