Solución para el caso simple
Como se explica en las respuestas a las que se hace referencia a continuación, puede usar tipos registrados (fila) y, por lo tanto, declarar implícitamente el tipo de retorno de una función polimórfica:
CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;
Llamar:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Devuelve la tabla completa (con todas las columnas de usuario).
¡Espera! ¿Cómo?
Explicación detallada en esta respuesta relacionada, capítulo "Varios tipos de tablas completas" :
- Refactorice una función PL/pgSQL para devolver el resultado de varias consultas SELECT
TABLE foo
es la abreviatura de SELECT * FROM foo
:
- ¿Existe un atajo para SELECCIONAR * DESDE?
2 pasos para un tipo de retorno completamente dinámico
Pero lo que intenta hacer es estrictamente imposible en un sencillo Comando SQL.
Quiero pasar schema_name
y table_name
como parámetros para funcionar y obtener la lista de registros, según column_visible
campo en public.fields
mesa.
No hay una forma directa de devolver una selección arbitraria de columnas (el tipo de devolución no se conoce en el momento de la llamada) desde una función, o cualquiera Comando SQL. SQL exige conocer el número, los nombres y los tipos de columnas resultantes en el momento de la llamada. Más en el segundo capítulo de esta respuesta relacionada:
- ¿Cómo genero un CROSS JOIN pivotado donde se desconoce la definición de la tabla resultante?
Hay varias soluciones alternativas . Puede envolver el resultado en uno de los tipos de documentos estándar (json
, jsonb
, hstore
, xml
).
O generas la consulta con una llamada de función y ejecutas el resultado con la siguiente:
CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
RETURNS text AS
$func$
SELECT format('SELECT %s FROM %I.%I'
, string_agg(quote_ident(column_name), ', ')
, schema_name
, table_name)
FROM fields
WHERE column_visible
AND schema_name = _schema_name
AND table_name = _table_name
GROUP BY schema_name, table_name
ORDER BY schema_name, table_name;
$func$ LANGUAGE sql;
Llamar:
SELECT public.generate_get_table('public', 'users');
Esto crea una consulta de la forma:
SELECT usr_id, usr FROM public.users;
Ejecutarlo en el segundo paso. (Es posible que desee agregar números de columna y ordenar columnas).
O agregue \gexec
en psql para ejecutar el valor devuelto inmediatamente. Ver:
Cómo forzar la evaluación de la subconsulta antes de unirse/presionar hacia un servidor externo
Asegúrese de defenderse contra la inyección SQL:
- INSERTAR con el nombre de la tabla dinámica en la función de activación
- ¿Definir nombres de tablas y columnas como argumentos en una función plpgsql?
varchar(100)
no tiene mucho sentido para los identificadores, que están limitados a 63 caracteres en Postgres estándar:
- Caracteres máximos en las etiquetas (nombres de tablas, columnas, etc.)
Si entiende cómo el tipo de identificador de objeto regclass
funciona, puede reemplazar el esquema y el nombre de la tabla con un solo regclass
columna.