Search code examples
sqltriggersconstraintsfirebird

How do I alter a CHECK constraint on Firebird?


I have a Firebird table like this:

CREATE TABLE events (
    event      VARCHAR(6)    NOT NULL
               CHECK (event IN ('deploy', 'revert', 'fail')),
    change_id  CHAR(40)      NOT NULL,
    change     VARCHAR(512)  NOT NULL
);

Now I need to add another value to the IN() list in the CHECK constraint. How do I do that?

Things I've tried so far:

  • Updating the value in RDB$TRIGGERS.RDB$TRIGGER_SOURCE:

    UPDATE RDB$TRIGGERS
       SET RDB$TRIGGER_SOURCE = 'CHECK (event IN (''deploy'', ''revert'', ''fail'', ''merge''))'
     WHERE RDB$TRIGGER_SOURCE = 'CHECK (event IN (''deploy'', ''revert'', ''fail''))';
    

    Does not seem to work, as the trigger is compiled in RDB$TRIGGERS.RDB$TRIGGER_BLR.

  • Creating a new table with a new check, copying the data over, dropping the old table and renaming the new table. However, it seems that one cannot rename a Firebird table, so I can't make the new table have the same name as the old one.

I suspect updating RDB$TRIGGERS is the way to go (idk!), if only I could get Firebird to recompile the code. But maybe there's a better way?


Solution

  • You need to drop and the re-create the check constraint.

    As you didn't specify a name for your constraint, Firebird created one, so you first need to find that name:

    select trim(cc.rdb$constraint_name), trg.rdb$trigger_source 
    from rdb$relation_constraints rc
      join rdb$check_constraints cc on rc.rdb$constraint_name = cc.rdb$constraint_name 
      join rdb$triggers trg on cc.rdb$trigger_name = trg.rdb$trigger_name 
    where rc.rdb$relation_name = 'EVENTS'
    and   rc.rdb$constraint_type = 'CHECK' 
    and   trg.rdb$trigger_type = 1;
    

    I just added the trigger source for informational reasons.

    Once you have the name, you can drop it, e.g.

    alter table events drop constraint integ_27;
    

    and then add the new constraint:

    alter table events 
        add constraint check_event_type 
            CHECK (event IN ('deploy', 'revert', 'fail', 'merge'));
    

    In the future you don't need to look for the constraint name because you already it.