How to add “on delete cascade” constraints?

前端 未结 3 642
无人共我
无人共我 2020-11-28 02:55

In PostgreSQL 8 is it possible to add ON DELETE CASCADES to the both foreign keys in the following table without dropping the latter?

# \\d scor         


        
相关标签:
3条回答
  • 2020-11-28 03:30

    I'm pretty sure you can't simply add on delete cascade to an existing foreign key constraint. You have to drop the constraint first, then add the correct version. In standard SQL, I believe the easiest way to do this is to

    • start a transaction,
    • drop the foreign key,
    • add a foreign key with on delete cascade, and finally
    • commit the transaction

    Repeat for each foreign key you want to change.

    But PostgreSQL has a non-standard extension that lets you use multiple constraint clauses in a single SQL statement. For example

    alter table public.scores
    drop constraint scores_gid_fkey,
    add constraint scores_gid_fkey
       foreign key (gid)
       references games(gid)
       on delete cascade;
    

    If you don't know the name of the foreign key constraint you want to drop, you can either look it up in pgAdminIII (just click the table name and look at the DDL, or expand the hierarchy until you see "Constraints"), or you can query the information schema.

    select *
    from information_schema.key_column_usage
    where position_in_unique_constraint is not null
    
    0 讨论(0)
  • 2020-11-28 03:35

    Usage:

    select replace_foreign_key('user_rates_posts', 'post_id', 'ON DELETE CASCADE');
    

    Function:

    CREATE OR REPLACE FUNCTION 
        replace_foreign_key(f_table VARCHAR, f_column VARCHAR, new_options VARCHAR) 
    RETURNS VARCHAR
    AS $$
    DECLARE constraint_name varchar;
    DECLARE reftable varchar;
    DECLARE refcolumn varchar;
    BEGIN
    
    SELECT tc.constraint_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name 
    FROM 
        information_schema.table_constraints AS tc 
        JOIN information_schema.key_column_usage AS kcu
          ON tc.constraint_name = kcu.constraint_name
        JOIN information_schema.constraint_column_usage AS ccu
          ON ccu.constraint_name = tc.constraint_name
    WHERE constraint_type = 'FOREIGN KEY' 
       AND tc.table_name= f_table AND kcu.column_name= f_column
    INTO constraint_name, reftable, refcolumn;
    
    EXECUTE 'alter table ' || f_table || ' drop constraint ' || constraint_name || 
    ', ADD CONSTRAINT ' || constraint_name || ' FOREIGN KEY (' || f_column || ') ' ||
    ' REFERENCES ' || reftable || '(' || refcolumn || ') ' || new_options || ';';
    
    RETURN 'Constraint replaced: ' || constraint_name || ' (' || f_table || '.' || f_column ||
     ' -> ' || reftable || '.' || refcolumn || '); New options: ' || new_options;
    
    END;
    $$ LANGUAGE plpgsql;
    

    Be aware: this function won't copy attributes of initial foreign key. It only takes foreign table name / column name, drops current key and replaces with new one.

    0 讨论(0)
  • 2020-11-28 03:39

    Based off of @Mike Sherrill Cat Recall's answer, this is what worked for me:

    ALTER TABLE "Children"
    DROP CONSTRAINT "Children_parentId_fkey",
    ADD CONSTRAINT "Children_parentId_fkey"
      FOREIGN KEY ("parentId")
      REFERENCES "Parent"(id)
      ON DELETE CASCADE;
    
    0 讨论(0)
提交回复
热议问题