Get all the rows referencing (via foreign keys) a particular row in a table

前端 未结 3 1778
你的背包
你的背包 2021-01-04 06:14

This seems so simple, but I haven\'t been able to find an answer to this question.

What do I want? A master table with rows that delete themselves w

相关标签:
3条回答
  • 2021-01-04 06:36
    SELECT * 
    FROM master ma
    WHERE EXISTS (
        SELECT *
        FROM other ot
        WHERE ot.master_id = ma.id
        );
    

    Or, the other way round:

    SELECT * 
    FROM other ot
    WHERE EXISTS (
        SELECT *    
        FROM master ma
        WHERE ot.master_id = ma.id
        );
    

    SO if you want to update (or delete) only the rows in master that are not referenced by other, you could:

    UPDATE master ma
    SET id = 1000+id
      , name = 'blue'
    WHERE name = 'green'
    AND NOT EXISTS (
        SELECT *
        FROM other ot
        WHERE ot.master_id = ma.id
        );
    
    0 讨论(0)
  • 2021-01-04 06:44

    You can do one of the following:

    1) Add reference_count field to master table. Using triggers on detail tables increase the reference count whenever a row with this master_id is added. Decrease the count, when row gets deleted. When reference_count reaches 0 - delete the record.

    2) Use pg_constraint table (details here) to get the list of referencing tables and create a dynamic SQL query.

    3) Create triggers on every detail table, that deletes master_id in main table. Silence error messages with BEGIN ... EXCEPTION ... END.

    0 讨论(0)
  • 2021-01-04 06:48

    In case someone wants a real count of rows in all other tables that reference a given master row, here is some PL/pgSQL. Note that this works in plain case with single column constraints. It gets more involved for multi-column constraints.

    CREATE OR REPLACE FUNCTION count_references(master regclass, pkey_value integer,
        OUT "table" regclass, OUT count integer)
        RETURNS SETOF record 
        LANGUAGE 'plpgsql'
        VOLATILE 
    AS $BODY$
    declare
      x record;           -- constraint info for each table in question that references master
      sql text;           -- temporary buffer
    begin
      for x in
        select conrelid, attname
        from pg_constraint
        join pg_attribute on conrelid=attrelid and attnum=conkey[1]
        where contype='f' and confrelid=master
          and confkey=( -- here we assume that FK references master's PK
            select conkey
            from pg_constraint
            where conrelid=master and contype='p'
          )
      loop
        "table" = x.conrelid;
        sql = format('select count(*) from only %s where %I=$1', "table", x.attname);
        execute sql into "count" using pkey_value;
        return next;
      end loop;
    end
    $BODY$;
    

    Then use it like

    select * from count_references('master', 1) where count>0
    

    This will return a list of tables that have references to master table with id=1.

    0 讨论(0)
提交回复
热议问题