The only arithmetic operations that can be performed on datetime values are addition and subtraction. If a datetime value is the operand of addition, the other operand must be a duration. The specific rules governing the use of the addition operator with datetime values follow:
If one operand is a date, the other operand must be a date duration or labeled
duration of years, months, or days.
If one operand is a time, the other operand must be a time duration or a labeled
duration of hours, minutes, or seconds.
If one operand is a timestamp, the other operand must be a duration. Any type of duration is valid.
Neither operand of the addition operator can be a parameter marker.
The rules for the use of the subtraction operator on datetime values are not the same as those for addition because a datetime value cannot be subtracted from a duration, and because the operation of subtracting two datetime values is not the same as the operation of subtracting a duration from a datetime value. The specific rules governing the use of the subtraction operator with datetime values follow:
If the first operand is a date, the second operand must be a date, a date duration, a string representation of a date, or a labeled duration of years, months, or days.
If the second operand is a date, the first operand must be a date, or a string representation of a date.
If the first operand is a time, the second operand must be a time, a time duration, a string representation of a time, or a labeled duration of hours, minutes, or seconds.
If the second operand is a time, the first operand must be a time, or string representation of a time.
If the first operand is a timestamp, the second operand must be a timestamp, a
string representation of a timestamp, or a duration.
If the second operand is a timestamp, the first operand must be a timestamp or a
string representation of a timestamp.
Neither operand of the subtraction operator can be a parameter marker.
Dates can be subtracted, incremented, or decremented.
Subtracting Dates
The result of subtracting one date (DATE2) from another (DATE1) is a date duration that specifies the number of years, months, and days between the two dates. The data type of
the result is DECIMAL(8,0). If DATE1 is greater than or equal to DATE2, DATE2 is subtracted from DATE1. If DATE1 is less than DATE2, however, DATE1 is subtracted from DATE2, and the sign of the result is made negative. The following procedural description clarifies the steps involved in the operation RESULT = DATE1 - DATE2.
If DAY(DATE2) <= DAY(DATE1)
then DAY(RESULT) = DAY(DATE1) - DAY(DATE2).
If DAY(DATE2) > DAY(DATE1)
then DAY(RESULT) = N + DAY(DATE1) - DAY(DATE2)
where N = the last day of MONTH(DATE2).
MONTH(DATE2) is then incremented by 1.
If MONTH(DATE2) <= MONTH(DATE1)
then MONTH(RESULT) = MONTH(DATE1) - MONTH(DATE2).
If MONTH(DATE2) > MONTH(DATE1)
then MONTH(RESULT) = 12 + MONTH(DATE1) - MONTH(DATE2).
YEAR(DATE2) is then incremented by 1.
YEAR(RESULT) = YEAR(DATE1) - YEAR(DATE2).
For example, the result of DATE('3/15/2000') - '12/31/1999' is 215 (or, a duration of 0 years, 2 months, and 15 days).
Incrementing and Decrementing Dates
The result of adding a duration to a date, or of subtracting a duration from a date, is itself a date. (For the purposes of this operation, a month denotes the equivalent of a calendar page. Adding months to a date, then, is like turning the pages of a calendar, starting with the page on which the date appears.) The result must fall between the dates January 1,
0001 and December 31, 9999 inclusive. If a duration of years is added or subtracted, only the year portion of the date is affected. The month is unchanged, as is the day unless the result would be February 29 of a non-leap-year. In this case, the day is changed to 28, and
SQLWARN6 in the SQLCA is set to 'W' to indicate the end-of-month adjustment.
Similarly, if a duration of months is added or subtracted, only months and, if necessary, years are affected. The day portion of the date is unchanged unless the result would be invalid (September 31, for example). In this case, the day is set to the last day of the month, and SQLWARN6 in the SQLCA is set to 'W' to indicate the end-of-month adjustment.
Adding or subtracting a duration of days will, of course, affect the day portion of the date, and potentially the month and year. Adding a labeled duration of DAYS will not cause an end-of-month adjustment.
Date durations, whether positive or negative, may also be added to and subtracted from dates. As with labeled durations, the result is a valid date, and a warning indicator is set in the SQLCA whenever an end-of-month adjustment is necessary.
When a positive date duration is added to a date, or a negative date duration is subtracted from a date, the date is incremented by the specified number of years, months, and days, in that order. Thus DATE1 + X, where X is a positive DECIMAL(8,0) number, is equivalent to the expression:
DATE1 + YEAR(X) YEARS + MONTH(X) MONTHS + DAY(X) DAYS
When a positive date duration is subtracted from a date, or a negative date duration is added to a date, the date is decremented by the specified number of days, months, and years, in that order. Thus, DATE1 - X, where X is a positive DECIMAL(8,0) number, is equivalent to the expression:
DATE1 - DAY(X) DAYS - MONTH(X) MONTHS - YEAR(X) YEARS
When adding durations to dates, adding one month to a given date gives the same date one month later unless that date does not exist in the later month. In that case, the date is set to that of the last day of the later month. For example, January 28 plus one month gives February 28; and one month added to January 29, 30, or 31 results in either
February 28 or, for a leap year, February 29.
Note:
If one or more months is added to a given date and then the same number of months is subtracted from the result, the final date is not necessarily the same as the original date.
Times can be subtracted, incremented, or decremented.
Subtracting Times
The result of subtracting one time (TIME2) from another (TIME1) is a time duration that specifies the number of hours, minutes, and seconds between the two times. The data type of the result is DECIMAL(6,0). If TIME1 is greater than or equal to TIME2, TIME2 is subtracted from TIME1. If TIME1 is less than TIME2, however, TIME1 is subtracted from TIME2, and the sign of the result is made negative. The following procedural description clarifies the steps involved in the operation RESULT = TIME1 - TIME2.
If SECOND(TIME2) <= SECOND(TIME1)
then SECOND(RESULT) = SECOND(TIME1) - SECOND(TIME2).
If SECOND(TIME2) > SECOND(TIME1)
then SECOND(RESULT) = 60 + SECOND(TIME1) - SECOND(TIME2).
MINUTE(TIME2) is then incremented by 1.
If MINUTE(TIME2) <= MINUTE(TIME1)
then MINUTE(RESULT) = MINUTE(TIME1) - MINUTE(TIME2).
If MINUTE(TIME2) > MINUTE(TIME1)
then MINUTE(RESULT) = 60 + MINUTE(TIME1) - MINUTE(TIME2).
HOUR(TIME2) is then incremented by 1.
HOUR(RESULT) = HOUR(TIME1) - HOUR(TIME2).
For example, the result of TIME('11:02:26') - '00:32:56' is 102930 (a duration of 10 hours, 29 minutes, and 30 seconds).
Incrementing and Decrementing Times
The result of adding a duration to a time, or of subtracting a duration from a time, is itself a time. Any overflow or underflow of hours is discarded, thereby ensuring that the result is always a time. If a duration of hours is added or subtracted, only the hours portion of the time is affected. The minutes and seconds are unchanged.
Similarly, if a duration of minutes is added or subtracted, only minutes and, if necessary, hours are affected. The seconds portion of the time is unchanged.
Adding or subtracting a duration of seconds will, of course, affect the seconds portion of the time, and potentially the minutes and hours.
Time durations, whether positive or negative, also can be added to and subtracted from times. The result is a time that has been incremented or decremented by the specified number of hours, minutes, and seconds, in that order. TIME1 + X , where "X" is a
DECIMAL(6,0) number, is equivalent to the expression:
TIME1 + HOUR(X) HOURS + MINUTE(X) MINUTES + SECOND(X) SECONDS
Timestamps can be subtracted, incremented, or decremented.
Subtracting Timestamps
The result of subtracting one timestamp (TS2) from another (TS1) is a timestamp duration that specifies the number of years, months, days, hours, minutes, seconds, and microseconds between the two timestamps. The data type of the result is
DECIMAL(20,6). If TS1 is greater than or equal to TS2, TS2 is subtracted from TS1. If
TS1 is less than TS2, however, TS1 is subtracted from TS2 and the sign of the result is made negative. The following procedural description clarifies the steps involved in the operation RESULT = TS1 - TS2.
If MICROSECOND(TS2) <= MICROSECOND(TS1) then MICROSECOND(RESULT) = MICROSECOND(TS1) -
MICROSECOND(TS2).
If MICROSECOND(TS2) >MICROSECOND(TS1) then MICROSECOND(RESULT) = 1000000 +
MICROSECOND(TS1) - MICROSECOND(TS2) and SECOND(TS2) is incremented by 1.
The seconds and minutes part of the timestamps are subtracted as specified in the rules for subtracting times.
If HOUR(TS2) <= HOUR(TS1) then HOUR(RESULT) = HOUR(TS1) - HOUR(TS2).
If HOUR(TS2) > HOUR(TS1) then HOUR(RESULT) = 24 + HOUR(TS1) - HOUR(TS2) and DAY(TS2) is incremented by 1.
The date part of the timestamps is subtracted as specified in the rules for subtracting dates.
Incrementing and Decrementing Timestamps
The result of adding a duration to a timestamp, or of subtracting a duration from a timestamp, is itself a timestamp. Date and time arithmetic is performed as previously defined, except that an overflow or underflow of hours is carried into the date part of the result, which must be within the range of valid dates. Microseconds overflow into seconds.
Expressions within parentheses are evaluated first. When the order of evaluation is not specified by parentheses, exponentiation is applied after prefix operators (such as -, unary minus) and before multiplication and division. Multiplication and division are applied before addition and subtraction. Operators at the same precedence level are applied from left to right. The following table shows the priority of all operators.
Priority Operators
1 +, - (when used for signed numeric values)
2 **
3 *, /, CONCAT, ||
4 +, - (when used between two operands)
In the following example, operators are applied in the order shown by the numbers in the second row.
1.10 * (SALARY + BONUS) + SALARY / :VAR3
2 1 4 3
.-ELSE NULL---------------.
>>-CASE--+searched-when-clause -+--+-------------------------+--END-><
'simple-when-clause ---' '-ELSE-result-expression -' searched-when-clause:
.-----------------------------------------------------.
V |
|----WHEN-search-condition --THEN--+result-expression -+-+------|
'-NULL--------------' simple-when-clause:
|-expression --------------------------------------------------->
.-----------------------------------------------.
V |
>----WHEN-expression --THEN--+result-expression -+-+------------|
'-NULL--------------'
CASE expressions allow an expression to be selected based on the evaluation of one or more conditions. In general, the value of the case-expression is the value of the resultexpression following the first (leftmost) when-clause that evaluates to true. If no whenclause evaluates to true and the ELSE keyword is present then the result is the value of the ELSE result-expression or NULL. If no when-clause evaluates to true and the ELSE keyword is not present then the result is NULL. Note that when a when-clause evaluates to unknown (because of nulls), the when-clause is not true and hence is treated the same way as a when-clause that evaluates to false.
The search-condition in a searched-when-clause cannot contain a basic predicate with a subselect, a quantified predicate, an IN predicate using a subselect, or an EXISTS predicate.
When using the simple-when-clause , the value of the expression prior to the first WHEN keyword is tested for equality with the value of the expression following the WHEN keyword(s). The data type of the expression prior to the first WHEN keyword must therefore be compatible with the data types of each expression following the WHEN keyword(s).
A result-expression is an expression following the THEN or ELSE keywords. There must be at least one result-expression in the CASE expression (NULL cannot be specified for every case). All result-expressions must have compatible data types, where the attributes of the result are determined based on the "Rules for Result Data Types" .
There are two scalar functions, NULLIF and COALESCE, that are specialized to handle a subset of the functionality provided by CASE. The following table shows the equivalent expressions using CASE or these functions.
Table 18. Equivalent CASE Expressions
CASE Expression
CASE WHEN e1=e2 THEN NULL ELSE e1 END
Equivalent Expression
NULLIF(e1,e2)
CASE WHEN e1 IS NOT NULL THEN e1 ELSE e2 END COALESCE(e1,e2)
CASE WHEN e1 IS NOT NULL THEN e1 ELSE
COALESCE(e2,...,eN) END COALESCE(e1,e2,...,eN)
If the first character of a department number is a division in the organization, then a CASE expression can be used to list the full name of the division to which each employee belongs:
SELECT EMPNO, LASTNAME,
CASE SUBSTR (WORKDEPT,1,1)
WHEN 'A' THEN 'Administration'
WHEN 'B' THEN 'Human Resources'
WHEN 'C' THEN 'Accounting'
WHEN 'D' THEN 'Design'
WHEN 'E' THEN 'Operations'
END
FROM EMPLOYEE
The number of years of education are used in the EMPLOYEE table to give the education level. A CASE expression can be used to group these and to show the level of education.
SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME,
CASE
WHEN EDLEVEL < 15 THEN 'SECONDARY'
WHEN EDLEVEL < 19 THEN 'COLLEGE'
ELSE 'POST GRADUATE'
END
FROM EMPLOYEE
Another interesting example of CASE statement usage is in protecting from division by 0 errors. For example, the following code finds the employees who earn more than 25% of their income from commission, but who are not fully paid on commission:
SELECT EMPNO, WORKDEPT, SALARY+COMM
FROM EMPLOYEE
WHERE (CASE WHEN SALARY=0 THEN NULL
ELSE COMM/SALARY
END) > 0.25
The following CASE expressions are equivalent:
SELECT LASTNAME,
CASE
WHEN LASTNAME = 'Haas' THEN 'President'
...
SELECT LASTNAME,
CASE LASTNAME
WHEN 'Haas' THEN 'President'
...
(1)
>>-CAST--(--+expression -------+--AS-data-type -------)--------><
+-NULL-------------+
'parameter-marker -'
Notes:
1.
The data type names may be qualified. For more information see Naming
Conventions .
data-type:
|--+built-in-type -+--------------------------------------------|
'distinct-type -' built-in-type:
|--+---BIGINT----------------------------------------------------------
---------------+--|
+-+-INTEGER-+-------------------------------------------------------
---------------+
| '-INT-----'
|
+---SMALLINT--------------------------------------------------------
---------------+
+-+-DECIMAL-+--+------------------------------+---------------------
---------------+
| +-DEC-----+ '-(-integer --+-----------+--)-'
|
| '-NUMERIC-' ', integer -'
|
+-+-FLOAT--+---------------+-+--------------------------------------
---------------+
| | '-(-integer --)-' |
|
| +-REAL---------------------+
|
| '-DOUBLE--+-----------+----'
|
| '-PRECISION-'
|
+---+-BLOB----------------+----+----------------------+-------------
---------------+
| '-BINARY LARGE OBJECT-' '-(-integer --+---+--)-'
|
| +-K-+
|
| '-M-'
|
+-+-+-CHARACTER-+--+---------------+-------------------------+--+---
-------------+-+
| | '-CHAR------' '-(-integer --)-' | +-
FOR BIT DATA---+ |
| +---+-VARCHAR----------------+--(-integer --)--------------+ +-
FOR SBCS DATA--+ |
| | '-+-CHARACTER-+--VARYING-' | +-
FOR MIXED DATA-+ |
| | '-CHAR------' | '-
CCSID-integer -' |
| '---+-CLOB-------------------+----+----------------------+-'
|
| +-CHAR LARGE OBJECT------+ '-(-integer --+---+--)-'
|
| '-CHARACTER LARGE OBJECT-' +-K-+
|
| '-M-'
|
+-+---GRAPHIC----+---------------+---------+--+----------------+----
---------------+
| | '-(-integer --)-' | '-CCSID-integer -'
|
| +---+-VARGRAPHIC------+--(-integer --)---+
|
| | '-GRAPHIC VARYING-' |
|
| '---DBCLOB----+----------------------+---'
|
| '-(-integer --+---+--)-'
|
| +-K-+
|
| '-M-'
|
+---DATE------------------------------------------------------------
---------------+
+---TIME------------------------------------------------------------
---------------+
+---TIMESTAMP-------------------------------------------------------
---------------+
'---DATALINK--+---------------+--+----------------+-----------------
---------------'
'-(-integer --)-' '-CCSID-integer -'
The CAST specification returns the cast operand (the first operand) cast to the type specified by the data type . If the data type of either operand is a distinct type, the privileges held by the authorization ID of the statement must include USAGE authority on the distinct type. expression
If the cast operand is an expression (other than parameter marker or NULL), the result is the argument value converted to the specified target data type.
NULL
The supported casts are shown in Table 9 , where the first column represents the data type of the cast operand (source data type) and the data types across the top represent the target data type of the CAST specification. If the cast is not supported, an error will occur.
When casting character or graphic strings to a character or graphic string with a different length, a warning is returned if truncation of other than trailing blanks occurs.
If the cast operand is the keyword NULL, the result is a null value that has the specified data type . parameter-marker
A parameter marker (specified as a question mark character) is normally considered an expression, but is documented separately in this case because it has a special meaning. If the cast operand is a parameter-marker , the specified data type is considered a promise that the replacement will be assignable to the specified data type (using the same rules as assignment to a column). Such a parameter marker is considered a typed parameter marker . Typed parameter markers will be treated like any other typed value for the purpose of DESCRIBE of a select list or for column assignment.
data-type
Specifies the data type of the result. If the data type is not qualified, the SQL path is used to find the appropriate data type. See CREATE TABLE for a description of data-type .
If length, precision, scale, or CCSID attributes are specified, the specified attributes are used. If the length, precision, or scale attributes are not specified, the default values are used. For example, the default for CHAR is a length of 1, and the default for DECIMAL is a precision of 5 and a scale of 0. For the default attribute values of the other data types, see CREATE TABLE . (For portability across operating systems, when specifying a floating-point data type, use REAL or DOUBLE instead of FLOAT.)
If the CCSID attribute is not specified, then:
If the data-type is BLOB, a CCSID of 65535 is used.
If the expression is a character string, and the data-type is CHAR,
VARCHAR, or CLOB; the CCSID of the expression is used.
If the expression is a graphic string, and the data-type is GRAPHIC,
VARGRAPHIC, or DBCLOB; the CCSID of the expression is used.
Otherwise, the default CCSID for the data-type is used.
Restrictions on the supported data types are based on the specified cast operand.
For a cast operand that is an expression , see Table 9 for the target data
types that are supported based on the data type of the cast operand.
For a cast operand that is the keyword NULL, the target data type can be any data type.
For a cast operand that is a parameter marker, the target data type can be any data type. If the data type is a distinct type, the application that uses the parameter marker will use the source data type of the distinct type.
For information on which casts between data types are supported and the rules for casting to a data type see Casting Between Data Types .
An application is only interested in the integer portion of the SALARY column
(defined as DECIMAL(9,2)) from the EMPLOYEE table. The following CAST specification will convert the SALARY column to INTEGER.
SELECT EMPNO, CAST( SALARY AS INTEGER)
FROM EMPLOYEE
Assume that two distinct types exist. T_AGE was sourced on SMALLINT and is the data type for the AGE column in the PERSONNEL table. R_YEAR was sourced on INTEGER and is the data type for the RETIRE_YEAR column in the same table. The following UPDATE statement could be prepared. An application is only interested in the integer portion of the SALARY column (defined as
DECIMAL(9,2)) from the EMPLOYEE table. The following CAST specification will convert the SALARY column to INTEGER.
UPDATE PERSONNEL SET RETIRE_YEAR = ?
WHERE AGE = CAST( ? AS T_AGE )
[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]