Saturday, February 22, 2025

Safely drop temporary table without dropping regular table with same name

 In PostgreSQL, it allows to create temporary table with same name as existing regular table, in such case, temporary table has higher "visibility" than regular table.

Once you drop the temporary table, you can see the data in regular table again. But, if you issue drop table twice, then you drop both temporary table and regular table.

How to prevent regular table being dropped? 

Here is a wrapper to safeguard this:

  1. -- Function to drop a temporary table if it exists
  2. CREATE OR REPLACE FUNCTION drop_temp_table_if_exists(table_name text)
  3. RETURNS void AS $$
  4. DECLARE
  5. temp_schema text;
  6. BEGIN
  7. -- Find the temporary schema name for the current session
  8. SELECT nspname INTO temp_schema
  9. FROM pg_namespace
  10. WHERE oid = pg_my_temp_schema();
  11. -- Check if the table exists in the temporary schema
  12. IF EXISTS (
  13. SELECT 1
  14. FROM pg_class c
  15. JOIN pg_namespace n ON c.relnamespace = n.oid
  16. WHERE n.nspname = temp_schema
  17. AND c.relname = table_name
  18. AND c.relkind = 'r' -- 'r' indicates a regular table (in this context, a temp table)
  19. ) THEN
  20. -- Construct the dynamic SQL to drop the table
  21. EXECUTE format('DROP TABLE %I', table_name);
  22. END IF;
  23. END;
  24. $$ LANGUAGE plpgsql;

Demonstration:
  1. mytest=# create table t1 (n text);
  2. CREATE TABLE
  3. Time: 4.322 ms
  4. mytest=# insert into t1 values ('regular');
  5. INSERT 0 1
  6. Time: 3.518 ms
  7. mytest=# create temporary table t1 (n text);
  8. CREATE TABLE
  9. Time: 3.192 ms
  10. mytest=# insert into t1 values ('temporary');
  11. INSERT 0 1
  12. Time: 2.869 ms
  13. mytest=# select * from t1;
  14. n
  15. -----------
  16. temporary
  17. (1 row)
  18. mytest=# SELECT drop_temp_table_if_exists('t1');
  19. drop_temp_table_if_exists
  20. ---------------------------
  21. (1 row)
  22. Time: 5.620 ms
  23. mytest=# select * from t1;
  24. n
  25. ---------
  26. regular
  27. (1 row)
  28. Time: 0.251 ms
  29. mytest=# SELECT drop_temp_table_if_exists('t1');
  30. drop_temp_table_if_exists
  31. ---------------------------
  32. (1 row)
  33. Time: 0.740 ms
  34. mytest=# select * from t1;
  35. n
  36. ---------
  37. regular
  38. (1 row)
  39. Time: 0.410 ms

No comments:

Post a Comment