SQL on DB2 for z/OS often needs “now”, “today”, or “as of last Tuesday” without the application passing a host variable. Datetime special registers read the processor clock. Temporal registers steer system-period and business-time tables. This page also covers CURRENT LOCK TIMEOUT (Db2 13), which lives in the same checklist even though it is a lock wait, not a clock.
| Register | Type | Notes |
|---|---|---|
| CURRENT DATE | DATE | Clock at the server; CURRENT_DATE synonym |
| CURRENT TIME | TIME | Same clock reading as other datetime registers in the statement |
| CURRENT TIMESTAMP | TIMESTAMP(6) default | Optional (0–12); WITH TIME ZONE form; SYSDATE = TIMESTAMP(0) |
| CURRENT TIME ZONE | DECIMAL(6,0) | UTC versus local duration from CLOCKxx |
| CURRENT TEMPORAL SYSTEM_TIME | TIMESTAMP(12) or NULL | Implicit FOR SYSTEM_TIME AS OF |
| CURRENT TEMPORAL BUSINESS_TIME | TIMESTAMP(12) or NULL | Implicit FOR BUSINESS_TIME AS OF |
| CURRENT LOCK TIMEOUT | INTEGER (Db2 13) | Seconds to wait for locks; NULL = IRLMRWT |
CURRENT DATE, CURRENT TIME, and CURRENT TIMESTAMP are stored internally as datetime values. When two or more of them appear — explicitly or as a column default — in one SQL statement, they represent the same point in time. Db2 takes one time-of-day clock reading, adds the TIMEZONE parameter from SYS1.PARMLIB(CLOCKxx), and treats the result as local date/time/timestamp at the server that executes the statement.
The documented exception is a non-atomic multiple-row INSERT or MERGE, where rows can see different readings.
You cannot SET these three registers. z/OS SET CLOCK and SET DATE can move the underlying clock and therefore the register values. Distributed SQL evaluates them at the server, not at the requester.
Inside a stored procedure or UDF, each SQL statement normally gets a new clock reading. If that routine runs in the scope of a trigger, Db2 uses the timestamp of the triggering statement instead, so trigger actions stay aligned with the INSERT or UPDATE that fired them.
CURRENT DATE (also CURRENT_DATE) is a DATE from that single clock reading at the current server.
123456SELECT AVG(YEAR(CURRENT DATE - BIRTHDATE)) FROM DSN8C10.EMP; SELECT EMPNO, LASTNAME FROM DSN8C10.EMP WHERE HIREDATE <= CURRENT DATE;
Prefer a range on the column (HIREDATE BETWEEN … AND CURRENT DATE) when you can keep the predicate indexable. Wrapping the column in YEAR(HIREDATE) = YEAR(CURRENT DATE) is harder on access paths.
CURRENT TIME (also CURRENT_TIME) is a TIME from the same clock reading. Combining it with CURRENT DATE in one SELECT gives a consistent “now” split across two columns.
12SELECT DSN8C10.PROJACT.*, CURRENT DATE, CURRENT TIME FROM DSN8C10.PROJACT;
CURRENT TIMESTAMP (also CURRENT_TIMESTAMP) is a timestamp from the same clock. Default precision is 6. You can request another precision:
12345678SELECT * FROM SYSIBM.SYSCOPY WHERE TIMESTAMP > CURRENT TIMESTAMP - 7 DAYS; INSERT INTO IN_TRAY VALUES (CURRENT TIMESTAMP, :SRC, :SUB, :TXT); SELECT CURRENT TIMESTAMP(8) WITH TIME ZONE FROM SYSIBM.SYSDUMMY1;
If you compare CURRENT TIMESTAMP (without WITH TIME ZONE) to a TIMESTAMP WITH TIME ZONE column, the implicit zone comes from the implicit time zone system parameter, which can differ from CURRENT TIME ZONE. Use CURRENT TIMESTAMP WITH TIME ZONE when the context is zoned.
Do not use CURRENT TIMESTAMP as the only uniqueness scheme for a multi-row INSERT. Every row of that one statement can receive the same value. Sequences, identity columns, and GENERATE_UNIQUE exist for that job.
CURRENT TIME ZONE (also CURRENT TIMEZONE and CURRENT_TIMEZONE) is the difference between UTC and local time as defined by the current server, if SESSION TIME ZONE has not been set. Local difference comes from z/OS CLOCKxx TIMEZONE. Data type DECIMAL(6,0): a time duration — two digits hours, two minutes, two seconds. Hours are adjusted to fit between −24 and 24 exclusive.
Subtracting CURRENT TIME ZONE from a local time converts that local time to UTC.
12SELECT RECEIVED - CURRENT TIME ZONE, SOURCE, SUBJECT, NOTE_TEXT FROM IN_TRAY;
SESSION TIME ZONE is a different register (VARCHAR(128), form ±th:tm, SET SESSION TIME ZONE). After you SET it, SESSION TIME ZONE and CURRENT TIME ZONE might no longer describe the same offset. CURRENT TIMESTAMP WITH TIME ZONE still takes the zone from CURRENT TIME ZONE per the SQL Reference.
CURRENT TEMPORAL SYSTEM_TIME is a TIMESTAMP(12) used as the default SYSTEM_TIME period for system-period temporal tables. Initial value is null in ordinary application SQL (inherited from the invoker in a trigger or an INHERIT SPECIAL REGISTERS routine; null under DEFAULT SPECIAL REGISTERS).
When the register is not null and a query references a system-period temporal table, Db2 implies:
1FOR SYSTEM_TIME AS OF CURRENT TEMPORAL SYSTEM_TIME
With SYSTIMESENSITIVE YES, you cannot also write FOR SYSTEM_TIME explicitly on that select-statement. SET CURRENT TEMPORAL SYSTEM_TIME is not a committable operation; ROLLBACK does not restore the old value. A SET inside a routine is not passed back to the caller.
123456SET CURRENT TEMPORAL SYSTEM_TIME = TIMESTAMP('2008-01-01') + 5 DAYS; SET CURRENT TEMPORAL SYSTEM_TIME = NULL; SELECT * FROM STT WHERE POLICY_ID = 123; -- equivalent to FOR SYSTEM_TIME AS OF current register when not null
CURRENT TEMPORAL BUSINESS_TIME is the application-period counterpart: TIMESTAMP(12), initially null, SET with SET CURRENT TEMPORAL BUSINESS_TIME.
BUSTIMESENSITIVE YES is the bind option that lets this implicit period apply. The same nested-routine rule holds: SET inside a procedure does not change the caller’s register.
123456SET CURRENT TEMPORAL BUSINESS_TIME = TIMESTAMP('2011-01-01') + 5 DAYS; SELECT SOURCE, SUBJECT FROM IN_TRAY WHERE DATE(CURRENT TEMPORAL BUSINESS_TIME) = DATE(RECEIVED);
CURRENT LOCK TIMEOUT is not a datetime value. It is grouped here because the special-register checklist places it with the temporal family. It arrived in Db2 13 function level 500 so an application can override the subsystem IRLM wait (IRLMRWT, often 30 seconds) without a ZPARM change.
Data type INTEGER, seconds. SET CURRENT LOCK TIMEOUT accepts:
Subsystem parameter SPREG_LOCK_TIMEOUT_MAX can cap how large a value an application is allowed to SET (−1 means no extra cap). CURRENT LOCK TIMEOUT also applies to similar waits such as claims and drains. It does not apply to P-locks or plan/package allocation locks.
123SET CURRENT LOCK TIMEOUT = 50; SET CURRENT LOCK TIMEOUT = NOT WAIT; SET CURRENT LOCK TIMEOUT = NULL;
Profile tables can set this register for local as well as DDF applications starting in Db2 13 — unlike many other special-register profile attributes that remain DDF-oriented.
CURRENT DATE is “what day the big wall clock shows in the computer room.” CURRENT TIME is the time on that same clock. CURRENT TIMESTAMP is both written together. If you ask for the date and the timestamp in one sentence, Db2 looks at the clock once so the two answers cannot disagree. CURRENT TIME ZONE is how many hours that clock is ahead of or behind world UTC time. The temporal registers are a sticky note that says “pretend today is this old date” when you read history tables. CURRENT LOCK TIMEOUT is how long you are willing to wait in line for a toy someone else is holding — zero means you walk away at once, minus one means you wait until they finish or the teacher (deadlock) breaks it up.
1. If CURRENT DATE and CURRENT TIMESTAMP appear in the same SQL statement, which clock readings are used?
2. What is the default precision of CURRENT TIMESTAMP?
3. What data type is CURRENT TIME ZONE?
4. What does a non-null CURRENT TEMPORAL SYSTEM_TIME do to queries of system-period temporal tables?
5. CURRENT LOCK TIMEOUT = 0 means what on Db2 13?