Db2 SQLCODE

SQLCODE -530: Foreign key value has no parent

SQLCODE -530 (SQLSTATE 23503) means an INSERT or UPDATE tried to put a foreign key value in a child table when no matching parent row exists. Db2 refuses it to keep referential integrity.

Also written as SQL -530, SQLCODE=-530, SQLCODE = -530, db2 -530, sqlstate 23503, SQL0530N, db2 foreign key violation.

What it means

A foreign key ties a column, or a set of columns, in a child table to the primary key or a unique key of a parent table. ORDER_LINE.ORDER_NO might point at ORDER_HDR.ORDER_NO, for example. Once the constraint exists, Db2 checks it on every insert into the child and on every update of the foreign key columns. If the new value isn't in the parent table, the statement fails with -530 and SQLERRMC holds the constraint name.

A foreign key with a null in any of its columns isn't checked at all. Db2 treats it as having no parent, which is allowed. So -530 only appears for values that are fully filled in.

Only the failing statement is undone. Rows the program inserted earlier in the unit of work are still there until it commits or rolls back.

Common causes

  • Rows are loaded in the wrong order. The child rows go in before the parent rows, often because two jobs ran out of sequence.
  • The parent row was never added, for example because its own insert failed earlier and the error wasn't checked.
  • Another process deleted the parent row before the child was inserted.
  • The values look the same but aren't. Missing leading zeros or a difference in upper and lower case make the child's value differ from the parent's key.
  • An update changed the foreign key to a value that isn't in the parent table yet, such as a new department code that hasn't been set up.

How to find the problem

  1. Take the constraint name from SQLERRMC or the DSNT408I message.
  2. Look it up with SELECT CREATOR, TBNAME, REFTBCREATOR, REFTBNAME FROM SYSIBM.SYSRELS WHERE RELNAME = 'FKLINORD'. TBNAME is the child table and REFTBNAME is the parent.
  3. Get the foreign key columns from SYSIBM.SYSFOREIGNKEYS for the same RELNAME, then check whether the value your program used exists in the parent table.
  4. If the value seems to be there, display both in hex. A difference in case or padding is easy to miss on screen.

How to fix it

  • Insert the parent row first, then the children. In batch, schedule the parent load ahead of the child load.
  • Check the SQLCODE of the parent insert, so one failed parent doesn't turn into a stream of -530s.
  • Clean the key values before inserting, so they match the parent's format exactly.
  • If the parent really doesn't exist yet, agree with the data owner whether to create it, hold the child for later, or reject it.
  • For bulk loads, the LOAD utility with ENFORCE CONSTRAINTS removes rows that break the constraint and can write them to a discard data set instead of failing.

What it looks like

ORDLOAD - INSERT ORDER_LINE FAILED, ORDER 00915532 LINE 003
DSNT408I SQLCODE = -530, ERROR:  THE INSERT OR UPDATE VALUE OF FOREIGN KEY FKLINORD IS
         INVALID
DSNT418I SQLSTATE   = 23503 SQLSTATE RETURN CODE

Questions

What's the difference between -530 and -532?

-530 happens on the child side, when a new or changed foreign key has no parent. -532 happens on the parent side, when you try to delete a parent row that still has children.

Can I turn the check off for a load?

The LOAD utility can run with ENFORCE NO, but Db2 then puts the table space in CHECK-pending status until CHECK DATA confirms the data. That's a decision for the DBA.