Abstract

Informix Dynamic Server (IDS) supports cascading deletes like some other database products. If a row is deleted from a master table which is referenced by a FOREIGN KEY with ON DELETE CASCADE, any matching rows in the detail table are also automatically deleted.

However, there does not appear to be any syntax to enable that without dropping and recreating the foreign key constraint, which requires an exclusive lock on the table and any others linked with referential integrity constraints. Furthermore, if you wanted to implement this on an entire database, that would require significant SQL development.

While standard administrative procedures require dropping and recreating constraints, this article explores an alternative methodology for modifying system catalogs directly. Because this approach bypasses normal engine validation, it is intended for educational purposes and sandbox environments rather than production systems.

Content

The use case that resulted in this article was a customer who wanted to prepare a demo with a clean masked subset of live data. However, deleting unwanted rows was proving very difficult due to referential integrity. Knowing the one place in the system catalog where a flag denoting ON DELETE CASCADE is stored, we experimented successfully with updating that directly.

Examples in this article were produced with the provided stores_demo database in IDS 14.10.FC13W3 Developer Edition from Fix Central, which was the latest at the time, installed in a Rocky 9 Docker container as described here.

The following is the existing foreign key we will use as an example:

Copy to Clipboard


This is a non-destructive test to prove that deleting rows from the referenced primary table is not allowed:

Copy to Clipboard


That results in this error:


We can enable cascading deletes with:

Copy to Clipboard


However, it continues to fail in the same way until we force that table to be reread into the data dictionary:

Copy to Clipboard


The same DELETE test as above then works without error.

To do the same on all FOREIGN KEY constraints in the database, first back up current settings:

Copy to Clipboard


We can then set all except those on system catalog tables to have ON DELETE CASCADE with:

Copy to Clipboard


Reversion would be with:

Copy to Clipboard


You are not supposed to have both ON DELETE CASCADE and delete triggers. If you try, you get this error:


Using the trick UPDATE, we can arrange for both to exist, as in the following demonstration.

Firstly, revert the foreign key not to have ON DELETE CASCADE as above.

Then create the following audit table and trigger:

Copy to Clipboard


Then prepare test data in a temp table:

Copy to Clipboard


Then prove that the trigger works with a test that only affects the audit table:

Copy to Clipboard


This row was returned:

audit_time2026-02-20 16:37:46
audit_userinformix
audit_eventD
customer_num121
call_dtime2026-02-20 16:37:46
user_idmaryj
call_codeO
call_descrCustomer likes our merchandise. Requests that we stock more types of infant joggers. Will call back to place order.
res_dtime2008-07-10 14:06
res_descrSent note to marketing group of interest in infant joggers

Enable ON DELETE CASCADE:

Copy to Clipboard


The above trigger test still works, but no rows are returned when we cause cascading deletes:

Copy to Clipboard


This proves that, should you use the trick to enable ON DELETE CASCADE, any delete trigger does not fire if a cascading delete occurs, which is probably what we would want.

Caveats

In that state, “dbschema”, “myschema”, or “dbexport” output conflicting SQL, for example:

[informix@ifx ~]$ dbschema -d stores_demo -t cust_calls -q | grep -v revoke | cat -s

{ TABLE "informix".cust_calls row size = 531 number of columns = 7 index size = 31 }

create table "informix".cust_calls
  (
    customer_num integer,
    call_dtime datetime year to minute,
    user_id char(32)
        default user,
    call_code char(1),
    call_descr char(240),
    res_dtime datetime year to minute,
    res_descr char(240),
    primary key (customer_num,call_dtime)
  );

alter table "informix".cust_calls add constraint (foreign key
    (call_code) references "informix".call_type  on delete cascade
    constraint "informix".r108_20);
alter table "informix".cust_calls add constraint (foreign key
    (customer_num) references "informix".customer );

create trigger "informix".del_cust_calls delete on "informix".cust_calls
    referencing old as o
    for each row
        (
        insert into "informix".audit_cust_calls (audit_time,audit_user,
    audit_event,customer_num,call_dtime,user_id,call_code,call_descr,
    res_dtime,res_descr)  values (CURRENT year to fraction(3) ,USER ,
    'D' ,o.customer_num ,o.call_dtime ,o.user_id ,o.call_code ,o.call_descr
    ,o.res_dtime ,o.res_descr ));


That would fail with error -742 as already described when trying to recreate the table. It is therefore not a good idea to leave such a combination there permanently.

Conclusion

The trick described here can enable ON CASCADE DELETE on a running system with the tables involved fully in use, and provides an easy way to enable it across a whole database.

This methodology provides a low-impact path to enable ON DELETE CASCADE without some of the inherent overheads. As this involves non-standard system modifications, it is intended for testing environments, and future compatibility is not guaranteed.

Related

The following feature request submitted on 25 Mar 2024 is outstanding:

Support for ON DELETE SET NULL and ON UPDATE CASCADE clauses in FOREIGN KEY statements

Disclaimer

Suggestions above are provided “as is” without warranty of any kind, either express or implied, including without limitation any implied warranties of condition, uninterrupted use, merchantability, fitness for a particular purpose, or non-infringement.

Contact Us

If you have any questions or would like to find out more about this topic, please contact us.

Author