Not every working set belongs in a permanent DB2 table. Db2 for z/OS gives you two global temporary table families: declared (DGTT — DECLARE GLOBAL TEMPORARY TABLE) and created (CGTT — CREATE GLOBAL TEMPORARY TABLE). Both hold process-private rows in work file storage. They differ in catalog registration, the SESSION qualifier, ON COMMIT rules, logging, indexes, and which DML you may run. This page is the working reference for those choices.
“Global” in the statement names does not mean one shared copy of the rows for the whole subsystem. Each application process gets its own instance. Global means the statement family (and, for CGTT, a catalog description many programs can share).
| Trait | DGTT | CGTT |
|---|---|---|
| Statement | DECLARE GLOBAL TEMPORARY TABLE | CREATE GLOBAL TEMPORARY TABLE |
| Catalog | No permanent table description | Yes — SYSTABLES type G |
| Qualifier | SESSION (required / implied) | Normal schema (HR, BILLING, …) |
| Instance scope | This application process | This application process (description is shared) |
| Indexes | Yes | No (classic CGTT) |
| UPDATE / searched DELETE | Yes | Restricted (often all-rows DELETE only; no UPDATE) |
| ON COMMIT options | DELETE / PRESERVE / DROP TABLE | Rows do not survive the process; no DGTT-style ON COMMIT menu |
| Logging options | LOGGED (default) or NOT LOGGED | Lightly logged by design |
| Storage | Work file (needs 32 KB spaces) | Work file database |
Use DECLARE GLOBAL TEMPORARY TABLE when you need scratch data for the life of an application process and do not need a permanent, shareable catalog description. Unlike most DECLARE statements, this one is executable: embed it, run it in SPUFI, or PREPARE it dynamically. Db2 creates an empty instance. You populate it with INSERT. You can SELECT, UPDATE, and searched or positioned DELETE. When the process ends, Db2 deletes the rows and drops the description.
Db2 performs limited logging and locking compared with a base table, which is why DGTTs are attractive for staging keys and multi-step batch logic.
The qualifier for a declared temporary table is SESSION. If you write an unqualified name, Db2 still defines it as SESSION. After DECLARE, every later statement that refers to the table should use SESSION.table-name so you do not accidentally hit a permanent table with the same unqualified name.
123456789101112DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMP_EMP ( EMPNO CHAR(6) NOT NULL, SALARY DECIMAL(9,2), COMM DECIMAL(9,2) ) ON COMMIT PRESERVE ROWS; INSERT INTO SESSION.TEMP_EMP (EMPNO, SALARY, COMM) SELECT EMPNO, SALARY, COMM FROM HR.EMPLOYEE WHERE WORKDEPT = 'A00'; SELECT EMPNO FROM SESSION.TEMP_EMP;
Two programs can DECLARE SESSION.TEMP_EMP at the same time. Each has a private instance. The name is only unique inside the process, not across the subsystem.
You can list columns, use LIKE, or use AS (SELECT …) DEFINITION ONLY:
123456DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMPPROD AS (SELECT * FROM BASEPROD) DEFINITION ONLY INCLUDING IDENTITY COLUMN ATTRIBUTES INCLUDING COLUMN DEFAULTS ON COMMIT PRESERVE ROWS;
DEFINITION ONLY copies the shape, not the rows. INCLUDING IDENTITY COLUMN ATTRIBUTES copies identity definitions so generated keys still work on the DGTT. INCLUDING COLUMN DEFAULTS copies defaults. LIKE a base table is the other common shortcut. You still INSERT to fill the instance.
| Option | What happens at COMMIT |
|---|---|
| ON COMMIT DELETE ROWS | Default. All rows deleted at COMMIT unless a WITH HOLD cursor on this table is still open. |
| ON COMMIT PRESERVE ROWS | Rows remain after COMMIT until the process ends or you DELETE them. Disables thread reuse for that thread while the DGTT is active at commit. |
| ON COMMIT DROP TABLE | The DGTT itself is dropped at COMMIT if no WITH HOLD cursor is open. If a held cursor is open, rows are preserved instead. |
Choose DELETE ROWS when the scratch set is for one unit of work. Choose PRESERVE ROWS when a batch COMMITs between steps but must keep the working set. Remember the thread-reuse cost: CICS/IMS thread reuse is not available to a thread whose most recent commit still has an active PRESERVE DGTT. Choose DROP TABLE when the DECLARE is cheap and you want the object gone as soon as the unit of work ends.
| Option | Effect |
|---|---|
| LOGGED | Default. INSERT, UPDATE, DELETE are logged. CREATE and DROP of the DGTT are logged. Rollback can undo data changes. |
| NOT LOGGED ON ROLLBACK DELETE ROWS | Data changes are not logged. Default rollback behavior for NOT LOGGED: a ROLLBACK or ROLLBACK TO SAVEPOINT deletes all rows. |
| NOT LOGGED ON ROLLBACK PRESERVE ROWS | Data changes are not logged, and ROLLBACK keeps the rows. Use only when you accept surviving scratch data after a failed unit of work. |
LOGGED is the default and the safe choice. NOT LOGGED (available from Db2 11) skips logging of data changes; CREATE and DROP of the table are still logged. Indexes inherit the table’s logging attribute.
A well-known trap: if a DGTT is NOT LOGGED and an INSERT fails with SQLCODE -803 on a unique index, Db2 may empty the table. On a LOGGED DGTT the previous rows remain. Prefer LOGGED unless you have measured log volume and understand rollback semantics.
1234DECLARE GLOBAL TEMPORARY TABLE SESSION.STAGING ( KEYCOL INTEGER NOT NULL ) ON COMMIT DELETE ROWS NOT LOGGED ON ROLLBACK DELETE ROWS;
After DECLARE, you may CREATE INDEX on SESSION.table. Unique indexes are how you enforce “no duplicate keys” in the scratch set. Indexes live with the instance and disappear with it.
12CREATE UNIQUE INDEX SESSION.STAGING_UX ON SESSION.STAGING (KEYCOL);
You can declare NOT NULL on DGTT columns. Primary key and referential constraint support on DGTTs is narrower than on base tables — treat unique indexes plus NOT NULL as the practical integrity toolkit, and confirm the exact constraint list for your Db2 version in the SQL Reference. You cannot expect a DGTT to be the parent of a permanent foreign key.
Use CREATE GLOBAL TEMPORARY TABLE when many programs should share one description but each process only needs its own empty bag of rows. Db2 records the definition in the catalog. SYSIBM.SYSTABLES shows TYPE = 'G'. The qualifier is a normal schema, not SESSION.
123456789101112131415CREATE GLOBAL TEMPORARY TABLE HR.EMP_KEYS ( EMPNO CHAR(6) NOT NULL, WORKDEPT CHAR(3) ); -- In an application process: INSERT INTO HR.EMP_KEYS (EMPNO, WORKDEPT) SELECT EMPNO, WORKDEPT FROM HR.EMPLOYEE WHERE WORKDEPT = 'A00'; SELECT K.EMPNO, E.LASTNAME FROM HR.EMP_KEYS K JOIN HR.EMPLOYEE E ON E.EMPNO = K.EMPNO;
Operations on created temporary tables are lightly logged. Classic CGTT restrictions still shape design reviews:
CGTT shines when the shape is stable, many programs INSERT-then-SELECT, and you want to avoid DECLARE cost on a hot path. If you need indexes or UPDATE, use a DGTT.
The CGTT description is permanent until DROP TABLE. GRANT and REVOKE apply to that catalog object the way they apply to other tables (with the usual temporary-table caveats). A DGTT never appears as a lasting SYSTABLES row for your SESSION instance. That is why tools that only look at the catalog can “see” CGTTs and miss DGTTs.
For a DGTT:
For a CGTT, CREATE is a one-time DBA/DDL event. Each process that first uses the table gets an empty instance. When the process ends, that instance’s rows are gone; the catalog description remains for the next caller.
Application process means the Db2 thread / connection, not “a CICS transaction ID for all users.” Two users in two threads do not see each other’s temporary rows.
Both families store instance data in the work file database. That is the same space SQL sorts and some other work files use. Before DECLARE GLOBAL TEMPORARY TABLE can succeed, IBM requires a WORKFILE database with at least one table space whose page size is 32 KB. Users of temporary tables need USE authority on that temporary table space.
DBA implications:
Neither replaces a permanent table when the data must survive a new connection, be shared between users, or be recovered with COPY/RECOVER. Temporary tables are session scratch, not system of record.
A temporary table is a whiteboard on your desk. A DGTT is a whiteboard you pull out of the closet when you sit down (DECLARE) and put back when you leave; it has the word SESSION on the frame so nobody confuses it with the classroom’s real blackboard. A CGTT is a printed blank form kept in the office supply cabinet (the catalog). Everyone may take a fresh copy to their own desk, but they do not write on each other’s copies. COMMIT can erase the whiteboard (DELETE ROWS), leave the notes (PRESERVE), or throw the whiteboard away (DROP TABLE). The paper lives in the work-file cupboard, which is also where Db2 keeps scrap paper for sorting — if that cupboard is full, nobody can sort or scribble.
1. What qualifier must a declared global temporary table use?
2. What is the default ON COMMIT behavior for a DGTT?
3. Which statement is true of CREATE GLOBAL TEMPORARY TABLE?
4. What does NOT LOGGED mean on a DGTT?
5. Before DECLARE GLOBAL TEMPORARY TABLE can succeed, the subsystem needs: