Using temp table in PL/pgSQL procedure for cleaning tables

前端 未结 3 1349
萌比男神i
萌比男神i 2020-12-17 22:29

I\'m trying to delete all data related to a user id from a game database.

There is a table holding all games (each played by 3 players):

# select * f         


        
3条回答
  •  温柔的废话
    2020-12-17 22:48

    Besides explicitly creating a temporary table and then inserting into it, there is another, simpler, right way to do it: CREATE TEMP TABLE AS as recommended in the docs:

    This command is functionally similar to SELECT INTO, but it is preferred since it is less likely to be confused with other uses of the SELECT INTO syntax. Furthermore, CREATE TABLE AS offers a superset of the functionality offered by SELECT INTO.

    For Postgres 9.1 or later see below.

    It would also be more efficient to use DELETE .. USING .. instead of a sub-select.
    And yes, if you are not planning to keep using the temp table (in the same session) after the transaction is committed, add ON COMMIT DROP.

    Putting it all together, your function could look like this:

    CREATE OR REPLACE FUNCTION pref_delete_user(_id varchar)
      RETURNS void AS
    $func$
    BEGIN    
       CREATE TEMP TABLE tmp_gids ON COMMIT DROP AS
       SELECT gid FROM pref_scores WHERE id = _id;
    
       DELETE FROM pref_scores p
       USING  tmp_gids t
       WHERE  p.gid = t.gid;
    
       DELETE FROM pref_games p
       USING  tmp_gids t
       WHERE  p.gid = t.gid;
    
       -- more deletes ...    
    END
    $func$ LANGUAGE plpgsql;
    

    Data modifying CTE

    In modern day Postgres the above only makes sense for complicated operations where you need an actual temporary table to work with - for instance to create an index on it before you proceed.

    In Postgres 9.1 or later use data-modifying CTEs for simple cases like the one at hand:

       WITH gids AS (SELECT gid FROM pref_scores WHERE id = _id)
          , d1   AS (  
          DELETE FROM pref_scores p
          USING  gids t
          WHERE  p.gid = t.gid
          (
          -- more work using gids?
       DELETE FROM pref_games p
       USING  gids t
       WHERE  p.gid = t.gid;
    

提交回复
热议问题