Unwanted New Value Substitution

Previous Next

Within transitional constraints, all SQL occurrences of transition table columns are substituted by the current OLD and NEW column values of the current row event.

This is important whenever there are multiple occurrences of the transition table in a constraint SQL statement.

Example

Suppose you want to delete a parent record if the last child record is deleted. The constraint you have written reads:

DELETE FROM    parent p

WHERE NOT EXISTS

       (SELECT    'child record'

        FROM    child c

        WHERE    c.foreignkey = p.primarykey

       )

AND EXISTS

       (SELECT    'old child record'

        FROM    child c

        WHERE    OLD(c.foreignkey) = p.primarykey

       )

and has transition properties:

Transition Table:  CHILD

Alias:             C

Fire on Insert:    Never

Fire on Delete:    Always

Fire on Update:    Never

This is a corrective, transitional constraint on a child table. If the last record of the child table is deleted, this constraint should make sure the parent record is automatically deleted as well. Because of the OLD() function in the last clause, the child table is automatically the Transition Table. The constraint is only evaluated when a child record is deleted, because of the transition properties.

Whenever a child record is deleted, the c.foreignkey column name becomes NULL, because that is the NEW value in a Delete. This makes the outcome of this subquery uncertain and dependent on your database conventions regarding treatment of NULL values. This is not what you want.

The only place where you want to bind a current value to the statement is in the second mention of the transition table (the OLD(c.foreignkey) value).

The solution is to use different table aliases so you can specify this:

DELETE FROM    parent p

WHERE NOT EXISTS

       (SELECT  'child record'

        FROM   child c1

        WHERE   c1.foreignkey = p.primarykey

       )

AND EXISTS

       (SELECT  'old child record'

        FROM   child c2

        WHERE   OLD(c2.foreignkey) = p.primarykey

       )

and set transition properties:

Transition Table:  CHILD

Alias:             C2

Fire on Insert:    Never

Fire on Delete:    Always

Fire on Update:    Never