63

With SQL Server, I can execute code ad hoc T-SQL code with full procedural logic through SQL Server Management Studio, or any other client. I've begun working with PostgreSQL and have run into a bit of a difference in that PGSQL requires any logic to be embedded in a function.

Is there a way to execute PL/PGSQL code without creating an executing a function?

3 Answers3

81

Postgres 9

DO $$ 
-- declare
BEGIN
  /* pl/pgsql here */
END $$;
mpapec
  • 50,217
  • 8
  • 67
  • 127
chotchki
  • 4,258
  • 5
  • 34
  • 55
  • 4
    For anyone who found this answer and tried it only to get "ERROR: syntax error at or near "SELECT"", you need a BEGIN and END. DO $$ BEGIN /* pl/pgsql here */ END $$ – Greg Najda Aug 26 '13 at 02:31
  • 4
    But how can that code return a query result? If I put a SELECT in the pl/pgsql part I get `ERROR: query has no destination for result data` – isapir Dec 29 '15 at 02:14
  • 3
    @Igal: It can't. You cannot return anything from a `DO` statement. You might raise notices or write to a temporary table or open a cursor as possible workarounds. – Erwin Brandstetter Apr 29 '16 at 02:23
  • little change work for me When i used `$$DECLARE` instead of `$$` ----------------------------------------------------------------------------------------------- `DO $$DECLARE srno integer; BEGIN select into srno count(reg_count) from table_name where condition; raise notice 'Desired Count %', srno; END $$;` – Er. Amit Joshi Nov 19 '18 at 04:31
  • I was happy to see this work with an EF Core migration – jenson-button-event Mar 01 '22 at 14:11
6

No, not yet. Version 9.0 (still alpha) will have this option (do), you a have to wait until it's released.

Frank Heikens
  • 117,544
  • 24
  • 142
  • 135
1

I struggled to get this working because it's fairly strict about adding semi colons in exactly the right places. But once you get used to that it works well. Besides the inability to return records of course, however you can raise notices & exceptions and do the other workarounds like using temp tables as @ErwinBrandstetter pointed out in a comment above.

e.g.:

DO 
$$
BEGIN
  IF EXISTS(SELECT 'any rows?' 
              FROM {your_table} 
              WHERE {your_column} = 'blah')
  THEN
      RAISE NOTICE 'record exists';
  ELSE
      RAISE EXCEPTION 'record does not exist';
  END IF;

  DROP TABLE IF EXISTS foo;

  CREATE TEMP TABLE foo AS
  SELECT 'bar'::character varying(5) as baz;
END 
$$;

SELECT * FROM foo;
Davos
  • 5,066
  • 42
  • 66
  • I think the ability to return rows, similar to SQL Server/Oracle stored procedures, is coming in the next version of PostgreSQL. Why that has taken this long is beyond me. –  Dec 07 '17 at 17:22