Chapter 9 Numbers
Numeric Datatypes
The NUMBER Type
The PLS_INTEGER Type
The BINARY_INTEGER Type
The SIMPLE_INTEGER Type
if you compile your code natively and your situation is such that your variable will never be NULL and will never overflow,then the SIMPLE_INTEGER type will scream with better performance. Consider this example: Page250
- The BINARY_FLOAT and BINARY_DOUBLE Types
Number Conversions
The TO_NUMBER Function
The TO_CHAR Function page261
The CAST Function
An advantage of CAST, however, is that it is part of the ISO SQL standard, whereas the TO_CHAR and TO_NUMBER functions are not. If writing 100% ANSI-compliant code is important to you, you should investigate the use of CAST.
Implicit Conversions
Numeric Operators
**Numeric Functions **
Rounding and Truncation Functions
CEIL
Returns the smallest integer that is greater than or equal to the specified value. This integer is the “ceiling” over your value.
FLOOR
Returns the largest integer that is less than or equal to the specified value. This integer is the “floor” under your value.
ROUND
Performs rounding on a number. You can round with a positive number of decimal places (the number of digits to the right of the decimal point) and also with a negative number of decimal places (the number of digits to the left of the decimal point).
TRUNC
Truncates a number to the specified number of decimal places. TRUNC simply discards all values beyond the number of decimal places provided in the call.
- Numeric Function Quick Reference P273
Chapter 10 Dates and Timestamps
Datetime Datatypes
DATE
Stores a date and time, resolved to the second. Does not include time zone.
- TIMESTAMP
Stores a date and time without respect to time zone. Except for being able to resolve
time to the billionth of a second (nine decimal places of precision), TIMESTAMP
is the equivalent of DATE.
- TIMESTAMP WITH TIME ZONE
Stores the time zone along with the date and time value, allowing up to nine decimal
places of precision.
- TIMESTAMP WITH LOCAL TIME ZONE
Stores a date and time with up to nine decimal places of precision. This datatype is
sensitive to time zone differences. Values of this type are automatically converted
between the database time zone and the local (session) time zone. When values are
stored in the database, they are converted to the database time zone, but the local
(session) time zone is not stored. When a value is retrieved from the database, that
value is converted from the database time zone to the local (session) time zone.
Use one of the TIMESTAMP types if you need to track time down to a fraction of
a second.Use TIMESTAMP WITH LOCAL TIME ZONE if you want the database to automatically
convert a time between the database and session time zones.Use TIMESTAMP WITH TIME ZONE if you need to keep track of the session time
zone in which the data was entered.You can use TIMESTAMP in place of DATE. A TIMESTAMP that does not contain
subsecond precision takes up 7 bytes of storage, just like a DATE datatype does.
When your TIMESTAMP does contain subsecond data, it takes up 11 bytes of
storage.Getting the Current Date and Time
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
The following example illustrates some of these functions:
set SERVEROUTPUT on;
BEGIN
DBMS_OUTPUT.PUT_LINE('Session Timezone='||SESSIONTIMEZONE);
DBMS_OUTPUT.PUT_LINE('Session Timestamp='||CURRENT_TIMESTAMP);
DBMS_OUTPUT.PUT_LINE('DB Server Timestamp='||SYSTIMESTAMP);
DBMS_OUTPUT.PUT_LINE('DB Timezone='||DBTIMEZONE);
EXECUTE IMMEDIATE 'ALTER SESSION SET TIME_ZONE=DBTIMEZONE';
DBMS_OUTPUT.PUT_LINE('DB Timestamp='||CURRENT_TIMESTAMP);
-- Revert session time zone to local setting
EXECUTE IMMEDIATE 'ALTER SESSION SET TIME_ZONE=LOCAL';
END;
- Interval Datatypes
INTERVAL YEAR TO MONTH
Allows you to define an interval of time in terms of years and months.
INTERVAL DAY TO SECOND
Allows you to define an interval of time in terms of days, hours, minutes, and
seconds (including fractional seconds).
- When to Use INTERVALs
One use for INTERVAL types is when you need to look at the difference between two
datetime values.
/* File on web: interval_between.sql */
DECLARE
start_date TIMESTAMP;
end_date TIMESTAMP;
service_interval INTERVAL YEAR TO MONTH;
years_of_service NUMBER;
months_of_service NUMBER;
BEGIN
-- Normally, we would retrieve start and end dates from a database.
start_date := TO_TIMESTAMP('29-DEC-1988','dd-mon-yyyy');
end_date := TO_TIMESTAMP ('26-DEC-1995','dd-mon-yyyy');
-- Determine and display years and months of service
service_interval := (end_date - start_date) YEAR TO MONTH;
DBMS_OUTPUT.PUT_LINE(service_interval);
-- Use the new EXTRACT function to grab individual
-- year and month components.
years_of_service := EXTRACT(YEAR FROM service_interval);
months_of_service := EXTRACT(MONTH FROM service_interval);
DBMS_OUTPUT.PUT_LINE(years_of_service || ' years and '
|| months_of_service || ' months');
END;
Had I not used an INTERVAL type, I would have had to code something like the following:
months_of_service := ROUND(months_between(end_date, start_date));
years_of_service := TRUNC(months_of_service/12);
months_of_service := MOD(months_of_service,12);
Datetime Conversions
From Strings to Datetimes
Working with Time Zones
Converting Time Zones to Character Strings
Padding Output with Fill Mode
Date and Timestamp Literals
Date and timestamp literals,are part of the ISO SQL standard and have been supported since Oracle9i Database.They represent yet another option for you to use in getting values into datetime variables.A date literal consists of the keyword DATE followed by a date (and only a date) value in the following format:
DATE 'YYYY-MM-DD'
A timestamp literal consists of the keyword TIMESTAMP followed by a datetime value
in a very specific format:
TIMESTAMP 'YYYY-MM-DD HH:MI:SS[.FFFFFFFFF] [{+|-}HH:MI]'
- Interval Conversions
The function NUMTOYMINTERVAL (pronounced “num to Y M interval”) converts a
numeric value to an interval of type INTERVAL YEAR TO MONTH. The function
NUMTODSINTERVAL (pronounced “num to D S interval”) likewise converts a numeric
value to an interval of type INTERVAL DAY TO SECOND.
DECLARE
y2m INTERVAL YEAR TO MONTH;
BEGIN
y2m := NUMTOYMINTERVAL (10.5,'Year');
DBMS_OUTPUT.PUT_LINE(y2m);
END;
The output is:
+10-06
The next example converts a numeric value to an interval of type INTERVAL DAY TO
SECOND:
DECLARE
an_interval INTERVAL DAY TO SECOND;
BEGIN
an_interval := NUMTODSINTERVAL (1440,'Minute');
DBMS_OUTPUT.PUT_LINE(an_interval);
END;
The output is:
+01 00:00:00.000000
PL/SQL procedure successfully completed.
TO_YMINTERVAL converts a character string value into an INTERVAL YEAR TO
MONTH value.
TO_YMINTERVAL('Y-M')
TO_DSINTERVAL converts a character string into an INTERVAL DAY TO
SECOND value.
TO_DSINTERVAL('D HH:MI:SS.FF')
- Formatting Intervals for Display
You can pass an interval to TO_CHAR, but TO_CHAR will ignore any
format mask. For example:
DECLARE
y2m INTERVAL YEAR TO MONTH;
BEGIN
y2m := INTERVAL '40-3' YEAR TO MONTH;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(y2m,'YY "Years" and MM "Months"'));
END;
The output is the same as if no format mask had been specified:
+000040-03
If you’re not satisfied with the default conversion of intervals to character strings, you
can use the EXTRACT function:
DECLARE
y2m INTERVAL YEAR TO MONTH;
BEGIN
y2m := INTERVAL '40-3' YEAR TO MONTH;
DBMS_OUTPUT.PUT_LINE(
EXTRACT(YEAR FROM y2m) || ' Years and '
|| EXTRACT(MONTH FROM y2m) || ' Months'
);
END;
The output is:
40 Years and 3 Months
- Interval Literals
- CAST and EXTRACT
- The CAST Function
- The EXTRACT Function
The following example shows EXTRACT being used to check whether the current
month is November:
BEGIN
IF EXTRACT (MONTH FROM SYSDATE) = 11 THEN
DBMS_OUTPUT.PUT_LINE('It is November');
ELSE
DBMS_OUTPUT.PUT_LINE('It is not November');
END IF;
END;
- Date Arithmetic with Intervals and Datetimes
For example, to add 1,500 days, 4 hours, 30 minutes, and 2 seconds to the current date and time:
DECLARE
current_date TIMESTAMP;
result_date TIMESTAMP;
BEGIN
current_date := SYSTIMESTAMP;
result_date:= current_date + INTERVAL '1500 4:30:2' DAY TO SECOND;
DBMS_OUTPUT.PUT_LINE(result_date);
END;
DECLARE
end_of_may2008 TIMESTAMP;
next_month TIMESTAMP;
BEGIN
end_of_may2008 := TO_TIMESTAMP('31-May-2008', 'DD-Mon-YYYY');
next_month := TO_TIMESTAMP(ADD_MONTHS(end_of_may2008, 1));
DBMS_OUTPUT.PUT_LINE(next_month);
END;
The results are:
30-Jun-2008 00:00:00.000000
There is no SUBTRACT_MONTHS function, but you can call ADD_MONTHS with
negative month values. For example, use ADD_MONTHS(current_date, −1) in the
previous example to go back one month to the last day of April.