After INSERT, UPDATE, DELETE, and MERGE, a few related techniques show up constantly on DB2 for z/OS: emptying a table with TRUNCATE, inserting many rows in one statement, assigning several columns at once, and the difference between searched and positioned (and mass) DELETE. This page is the toolbox for those patterns.
TRUNCATE TABLE deletes all rows of a base table or a declared global temporary table. The table may live in a simple, segmented, partitioned, or universal table space. If the table has LOB or XML columns, those auxiliary table spaces and the indexes are truncated as well. Do not confuse this statement with the TRUNCATE numeric function.
You need DELETE privilege (or ownership / DBADM / DATAACCESS / SYSADM). IGNORE DELETE TRIGGERS also requires ALTER-level authority on the table. Row and column access control is not enforced for TRUNCATE.
123456789101112TRUNCATE TABLE INVENTORY DROP STORAGE IGNORE DELETE TRIGGERS; TRUNCATE TABLE INVENTORY REUSE STORAGE IGNORE DELETE TRIGGERS; TRUNCATE TABLE INVENTORY REUSE STORAGE IGNORE DELETE TRIGGERS IMMEDIATE;
| Option | Meaning |
|---|---|
| DROP STORAGE | Release allocated space at table-space scope (default) |
| REUSE STORAGE | Empty pages but keep them allocated to this table |
| IGNORE DELETE TRIGGERS | Do not fire delete triggers (default); extra ALTER-level auth |
| RESTRICT WHEN DELETE TRIGGERS | Error if any delete trigger is defined |
| IMMEDIATE | Cannot be undone; no uncommitted changes in the table space |
DROP STORAGE releases space at table-space level so any table in that space can reuse it. A later REORG (without REUSE) is still how shops fully tidy physical files; DROP STORAGE is not “delete the VSAM linear data set.”
REUSE STORAGE keeps the empty pages allocated to this table so the next insert wave does not have to grow storage as aggressively. It is ignored on simple table spaces (treated as DROP STORAGE).
IMMEDIATE means the truncate cannot be undone. The table must not have uncommitted updates; in a multi-table table space, uncommitted changes or uncommitted DDL on any table in the space cause failure. After IMMEDIATE, ROLLBACK still undoes other statements in the unit of work, but the table stays empty. Without IMMEDIATE, ROLLBACK can undo the truncate. IMMEDIATE also lets segmented and UTS tables reclaim space for inserts in the same unit of work without a commit.
Truncating a table does not reset an identity column’s next value on Db2 for z/OS. The next INSERT still continues the sequence. If you emptied a work table and want numbers to start over, alter the identity:
123456TRUNCATE TABLE HR.EMP_WORK REUSE STORAGE IGNORE DELETE TRIGGERS; ALTER TABLE HR.EMP_WORK ALTER COLUMN WORK_ID RESTART WITH 1;
RESTART WITH is an ALTER TABLE identity attribute, not a TRUNCATE clause (LUW’s RESTART IDENTITY / CONTINUE IDENTITY wording is a different product). Cache gaps can still appear if a restart is rolled back after unused cached values were assigned.
| Topic | DELETE FROM t | TRUNCATE TABLE t |
|---|---|---|
| Row filter | WHERE can keep some rows | Always all rows |
| DELETE triggers | Fire | Ignored (or statement restricted) |
| Parent in RI | Follows ON DELETE rule | Not allowed if constraint is enforced |
| Rollback | Ordinary transaction | Undoable unless IMMEDIATE |
| Identity next value | Unchanged | Unchanged — ALTER to RESTART |
TRUNCATE is refused if the table is a parent in an enforced RI constraint, even when the child has no rows. It is also refused for system-period temporal tables. Tables with CDC, multi-level security labels, or VALIDPROC may be processed more like a mass delete (row-by-row checks). Use DELETE when you need WHERE, triggers, or RI cascade.
MATCHED and NOT MATCHED are MERGE clauses, not DELETE clauses: they decide UPDATE/ DELETE versus INSERT when a source is applied to a target. See the MERGE page.
Embedded SQL can insert several rows in one INSERT using host-variable arrays and FOR n ROWS. Dynamic SQL can use a VALUES list with several rows. FOR n ROWS may appear on the INSERT or on the EXECUTE of a dynamic INSERT.
123INSERT INTO HR.EMP_STAGE (EMPNO, LASTNAME, SALARY) VALUES (:HV-EMPNO, :HV-LAST, :HV-SALARY) FOR :HV-NROWS ROWS;
Each host-variable array supplies one column. An indicator array is required when the SQLTYPE says the column is nullable. The number of rows must fit the array dimension and the FOR n ROWS count.
On a multi-row INSERT (and on MERGE with multi-row VALUES), NOT ATOMIC CONTINUE ON SQLEXCEPTION means a bad row does not undo rows already processed in that statement. The statement can return a warning or an error with a mix of successes. Without NOT ATOMIC, one failure fails the whole INSERT.
Use GET DIAGNOSTICS after the statement. ROW_COUNT (or the diagnostics area) tells how many row conditions to inspect. Loop DB2_GET_DIAGNOSTICS_DIAGNOSTICS / GET DIAGNOSTICS CONDITION n for SQLSTATE, SQLCODE, and DB2_ROW_NUMBER so the application can retry or report the failing slots.
123456GET DIAGNOSTICS :HV-ROWCOUNT = ROW_COUNT; -- Then for i from 1 to HV-ROWCOUNT: GET DIAGNOSTICS CONDITION :I :HV-SQLSTATE = RETURNED_SQLSTATE, :HV-SQLCODE = DB2_RETURNED_SQLCODE;
UPDATE (and MERGE UPDATE) can assign several columns at once:
12345678910UPDATE DSN8C10.EMP SET (SALARY, BONUS, COMM) = (NULL, NULL, NULL) WHERE EMPNO = '000250'; UPDATE HR.EMP_WORK E SET (DEPTNAME, LOCATION) = (SELECT D.DEPTNAME, D.LOCATION FROM HR.DEPARTMENT D WHERE D.DEPTNO = E.WORKDEPT) WHERE E.EMPNO = :HV-EMPNO;
The first form is a list of scalars. The second is a row-fullselect: one row, as many columns as the parenthesized target list. Zero rows assign nulls; extra rows are an error. Correlated UPDATE is the same idea with a correlation name on the target so the subquery can see the current row.
Mass DELETE is throwing every card in the drawer into the bin, one by one, while a librarian writes each name down (triggers) and checks family rules (RI). TRUNCATE is dumping the whole drawer at once. DROP STORAGE is putting the empty drawer back on the shared shelf; REUSE STORAGE is leaving the empty drawer on your desk. IMMEDIATE means you already burned the cards—you cannot glue them back. Multi-row INSERT is stuffing a handful of new cards in one motion; NOT ATOMIC means if one card is torn, the ones already in the drawer stay in.
1. What is the default storage option on TRUNCATE?
2. Can ROLLBACK undo TRUNCATE … IMMEDIATE?
3. Does TRUNCATE fire DELETE triggers by default?
4. Does TRUNCATE restart an identity column on z/OS?
5. What does NOT ATOMIC CONTINUE ON SQLEXCEPTION mean on multi-row INSERT?