¿Cómo crear una función temporal en PostgreSQL?

82

Tengo que ejecutar un bucle en la base de datos. Este es solo un requisito de una vez. Después de ejecutar la función, la descarto ahora.

¿Existe algún buen enfoque para crear funciones temporales / desechables?

Anand
fuente

Respuestas:

115

Necesitaba saber cómo usar el tiempo en un guión que estaba escribiendo. Resulta que puedes crear una función temporal usando el esquema pg_temp. Este es un esquema que se crea a pedido para su conexión y es donde se almacenan las tablas temporales. Cuando su conexión se cierra o caduca, este esquema se elimina. Resulta que si crea una función en este esquema, el esquema se creará automáticamente. Por lo tanto,

create function pg_temp.testfunc() returns text as 
$$ select 'hello'::text $$ language sql;

será una función que se mantendrá siempre que su conexión se mantenga. No es necesario llamar a un comando de caída.

Crowmagnumb
fuente
61

Un par de notas adicionales al truco inteligente en la respuesta de @ crowmagnumb :

  • La función debe estar calificada por esquema en todo momento, incluso si pg_tempestá en el search_path(como está por defecto), según Tom Lane para evitar los caballos de Troya:
CREATE FUNCTION pg_temp.f_inc(int)
  RETURNS int AS 'SELECT $1 + 1' LANGUAGE sql IMMUTABLE;

SELECT pg_temp.f_inc(42);
f_inc
-----
43
  • Una función creada en el esquema temporal solo es visible dentro de la misma sesión (al igual que las tablas temporales). Es invisible para todas las demás sesiones (incluso para el mismo rol). Usted podría tener acceso a la función como un papel diferente en la misma sesión después SET ROLE.

  • Incluso podría crear un índice funcional basado en esta función "temporal":

    CREATE INDEX foo_idx ON tbl (pg_temp.f_inc(id));
    

    De este modo, se crea un índice simple utilizando una función temporal en una tabla no temporal. Dicho índice sería visible para todas las sesiones, pero solo sería válido para la sesión de creación. El planificador de consultas no utilizará un índice funcional, donde la expresión no se repite en la consulta. Todavía es un truco sucio. Se eliminará automáticamente cuando se cierre la sesión, como un objeto dependiente. Siente que esto no debería permitirse en absoluto ...


Si solo necesita ejecutar una función repetidamente y todo lo que necesita es SQL, considere una declaración preparada en su lugar. Actúa de forma muy similar a una función SQL temporal que muere al final de la sesión. Sin embargo, no es lo mismo y solo se puede usar por sí mismo EXECUTE, no anidado dentro de otra consulta. Ejemplo:

PREPARE upd_tbl AS
UPDATE tbl t SET set_name = $2 WHERE tbl_id = $1;

Llamada:

EXECUTE upd_tbl(123, 'foo_name');

Detalles:

Erwin Brandstetter
fuente
30

Si está utilizando la versión 9.0, puede hacer esto con la nueva declaración DO:

http://www.postgresql.org/docs/current/static/sql-do.html

Con versiones anteriores, deberá crear la función, llamarla y soltarla nuevamente.

un caballo sin nombre
fuente
4
... Es útil para realizar scripts en la terminal, pero no puede volver a llamarlo, como una "función anónima" (o lambda), por lo que la instrucción DO no es tan útil como una "función temporal".
Peter Krauss
@PeterKrauss: si quieres volver a llamarlo, necesitas crear una función real.
a_horse_with_no_name
Por supuesto, mi a_hourse :-) Solo estaba mostrando la ruta teórica para implementar "temporal" ... Es por eso que la mejor respuesta (posible con PostgreSQL), para la pregunta principal, es pg_temp.foo(). No entiendo por qué (!?) Hoy, 2014, con ejemplos tan simples y rápidos como Lua , los lenguajes SQL DML no pueden ofrecer funciones lambda (!).
Peter Krauss
7
Además, las DOdeclaraciones no pueden tener parámetros de entrada y no pueden devolver un resultado, al contrario de las funciones.
Daniel Vérité
2
Si no regresa, ¿deberíamos llamarlo "función"?
AndreKR
-4

Para los procedimientos ad hock, los cursores no son tan malos. Sin embargo, son demasiado ineficientes para su uso productino.

Le permitirán recorrer fácilmente los resultados de SQL en la base de datos.

Byron Whitlock
fuente
6
¿Por qué cree que los cursores son ineficientes en PostgreSQL?
Frank Heikens
2
Los cursores mantienen una conexión de base de datos cuando se realiza un bucle. Una página web con cientos de cursores de larga duración eliminará las conexiones y pondrá de rodillas el sitio / la base de datos.
Byron Whitlock