Skip to content

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_DBCX_SY_OPEN_SQLCX_DYNAMIC_CHECKCX_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

Comments