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
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 theSELECT INTO
syntax. Furthermore,CREATE TABLE AS
offers a superset of the functionality offered bySELECT 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;
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;