1
BEGIN
   _table_name := 'mytable';

   CREATE TEMPORARY TABLE _table_name (
     id integer NOT NULL,
     name character varying,
     active boolean
   ) ON COMMIT DROP';

-- logic here

RETURN QUERY SELECT table1.id, table1.name FROM _table_name AS table1;
END;

I have simplified my problem. I'm trying to use a variable as the table name.

I know you can do things like SELECT * FROM table1 WHERE id = _id where _id is a declared varaible.

I know I can do this EXECUTE, but then I have a query like: INSERT INTO table2 (id) SELECT id FROM unnest(_ids) as id where _ids is an array.

Anyway to solve problem 1 with using a variable as table name? and problem 2, using unnest inside EXECUTE?

So the problem is that the queries take _table_name as a literal table name, it doesn't look like it's using 'mytable' as the table name instead.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
user962449
  • 3,743
  • 9
  • 38
  • 53
  • http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN –  Mar 09 '15 at 22:00
  • @a_horse_with_no_name I already read that. My argument was that how come you can use variables in literal queries like in the example with `_id` vs the create table example. – user962449 Mar 09 '15 at 22:03

2 Answers2

2

If you're dynamically changing the table name (i.e. via a variable) then you will need to use EXECUTE. You can use this with arrays and unnest, as long as you cast the arrays to/from a TEXT representation.

DECLARE 
    _ids INT[] = ARRAY[ 1, 2, 3, 4, 5 ];
    _table_name TEXT = 'mytable';
BEGIN 
  EXECUTE
    'INSERT INTO ' || QUOTE_IDENT( _table_name ) || ' (id)
     SELECT id
     FROM unnest( ' || QUOTE_LITERAL( _ids::TEXT ) || '::INT[] ) AS id';
END; 
Gareth Flowers
  • 1,513
  • 12
  • 23
1

You have been told about dynamic SQL with EXECUTE in plpgsql. You build the query string dynamically including invariable code and identifiers.

But do not concatenate values. Use the USING clause instead:

DECLARE 
   _ids INT[] = ARRAY[ 1, 2, 3, 4, 5 ];
   _table_name TEXT = 'mytable';
BEGIN 
   EXECUTE
    'INSERT INTO ' || quote_ident(_table_name) || ' (id)
     SELECT * FROM unnest($1)'
   USING ids;
END; 

Avoids error-prone casting back and forth.

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228