CX_SY_OPEN_SQL_DB¶
Raised for Open SQL database errors, including duplicate key violations.
Purpose¶
CX_SY_OPEN_SQL_DB is the class-based wrapper for database-level errors that occur during Open SQL DML statements (INSERT, UPDATE, MODIFY, DELETE). Introduced in ABAP 7.40, it replaces the older SY-SUBRC = 4 / SY-DBCNT pattern for bulk DML and provides structured error information instead of a short dump.
Inheritance chain:
CX_SY_OPEN_SQL_DB → CX_SY_OPEN_SQL → CX_DYNAMIC_CHECK → CX_ROOT
Key attributes¶
| Attribute | Type | Description |
|---|---|---|
db_error |
I |
Numeric database error code (DBSL layer code, DB-vendor-independent) |
internal_error |
STRING |
Internal ABAP runtime detail string; useful for log entries |
Neither attribute maps 1:1 to a raw DB error code (e.g. ORA-00001). Use get_text( ) for a human-readable message and db_error for programmatic branching.
Before ABAP 7.40
On releases below 7.40, a duplicate key on INSERT sets SY-SUBRC = 4 and does not raise an exception. The class-based approach only applies when the statement is written in strict 7.40+ syntax.
How to catch¶
INSERT with duplicate-key handling¶
TRY.
INSERT ztable FROM TABLE @lt_records.
CATCH cx_sy_open_sql_db INTO DATA(lx_db).
" If the exception is raised, NO rows from lt_records were written.
" The INSERT statement is atomic — it is all-or-nothing.
WRITE: / 'DB error:', lx_db->db_error,
/ lx_db->get_text( ).
ENDTRY.
Atomicity: zero rows on exception
When CX_SY_OPEN_SQL_DB is caught, the entire DML statement has been rolled back at the database level. No partial inserts/updates exist. Do not attempt to query how many rows succeeded — the answer is zero.
UPDATE / DELETE¶
TRY.
UPDATE ztable
SET status = 'X'
WHERE bukrs = @lv_bukrs.
CATCH cx_sy_open_sql_db INTO DATA(lx).
log_db_error( lx ).
RAISE EXCEPTION TYPE cx_finance_error
EXPORTING textid = cx_finance_error=>db_update_failed.
ENDTRY.
Distinguishing error types programmatically¶
TRY.
INSERT ztable FROM TABLE @lt_data.
CATCH cx_sy_open_sql_db INTO DATA(lx).
CASE lx->db_error.
WHEN 1. " Duplicate key (DBSL code 1)
handle_duplicates( lt_data ).
WHEN OTHERS.
" Deadlock, timeout, connection loss, etc.
RAISE EXCEPTION lx.
ENDCASE.
ENDTRY.
More than just duplicates
CX_SY_OPEN_SQL_DB fires for any database error, not only duplicate keys. Common triggers include:
- Deadlocks (two sessions locking each other)
- Lock wait timeouts
- Database connection loss
- Constraint violations other than primary key (foreign key, check constraint)
- Tablespace / quota exhaustion
Always inspect db_error and log get_longtext( ) before assuming the cause is a duplicate.
Common scenarios¶
Bulk load from file with duplicate tolerance¶
SPLIT lv_line AT '|' INTO TABLE lt_fields.
" ... build lt_records from lt_fields ...
TRY.
INSERT ztransaction FROM TABLE @lt_records.
CATCH cx_sy_open_sql_db INTO DATA(lx).
IF lx->db_error = 1.
" Re-try row-by-row or skip duplicates
insert_with_fallback( lt_records ).
ELSE.
RAISE EXCEPTION lx.
ENDIF.
ENDTRY.
Background job with structured error reporting¶
TRY.
DELETE FROM zlog WHERE timestamp < @lv_cutoff.
CATCH cx_sy_open_sql_db INTO DATA(lx).
MESSAGE lx->get_text( ) TYPE 'E'.
ENDTRY.
See also¶
- SAPSQL_ARRAY_INSERT_DUPREC — short dump analysis for SAPSQL_ARRAY_INSERT_DUPREC