2010-03-03 55 views
7

Soy bastante nuevo en el postgresql.Columna dinámica en la instrucción SELECT postgres

¿cuál es la mejor manera de lograrlo?

SELECT get_columns() 
    FROM table_name; 

get_columns() proporcionará los nombres de columna para la consulta. Vi a personas que aconsejaban usar la declaración EXECUTE pero no pude hacerlo funcionar.

permite decir que hay prueba de tabla con columnas a, b, c y quiero correr

SELECT a,b FROM Test; 
SELECT a,c FROM Test; 

con nombres de columna generadas dinámicamente.

+0

¿Cuál es el punto? Si no conoce los nombres de columna, simplemente use un * en su consulta. Tal vez me estoy perdiendo algo? –

+0

Lo que está diciendo es 'get_columns()' devolvería * cualquiera * columnas 'a' y' c' o columnas 'a' y' b'. Él no quiere todas las columnas, solo las generadas por procedimientos. – cmptrgeekken

+0

La idea es que get_columns() tome algún argumento y, por consiguiente, devolverá las columnas adecuadas para usar en algún lugar. Esta pieza será útil cuando se trata del comando COPY FROM en el que necesito proporcionar nombres de columna en función del archivo csv del que estoy seleccionando. – Sujit

Respuesta

-2

Esta es la forma de obtener los columnnames en una tabla:

SELECT 
    column_name 
FROM 
    information_schema.columns 
WHERE 
    table_name = 'test'; 
+1

Sí, lo sé. La pregunta es ¿podemos construir una instrucción SELECT de forma dinámica? – Sujit

0

Dado que está utilizando COPY FROM en una tabla grande conocida, CREATE una FUNCIÓN que devuelve SETOF bigtable y SELECCIONA todas las columnas del tipo específico, use NULL AS fieldname para los campos que no son necesarios en ese caso específico, algo como:

# \d SMALL 
    Table "public.small" 
Column | Type | Modifiers 
--------+---------+----------- 
a  | integer | 
b  | integer | 
c  | integer | 
d  | integer | 

# \d LARGE 
    Table "public.large" 
Column | Type | Modifiers 
--------+---------+----------- 
a  | integer | 
b  | integer | 
c  | integer | 
d  | integer | 

# CREATE OR REPLACE FUNCTION myData() 
RETURNS SETOF large LANGUAGE SQL AS $$ 
SELECT a, 
     CASE WHEN a = 1 
      THEN b 
     ELSE 
      NULL 
END as b, 
     CASE WHEN a = 2 
      THEN c 
     ELSE 
      NULL 
END AS c, 
d 
FROM small; 
$$; 

# SELECT * FROM mydata(); 
# COPY (SELECT * FROM myData()) TO STDOUT; 

Obviamente SQL podría no ser el mejor lenguaje a utilizar, por lo PL/pgSQL o PL/Perl (o lo que sea) puede ser apropiada.

+0

esto parece ser el camino equivocado, no dude en ignorar esta respuesta – MkV

0

No podrá utilizar una función para generar una lista de columnas. Y realmente no creo que esta es la mejor manera de abordar el problema ... Dicho esto, puede hacerlo con 8.4, así:

CREATE OR REPLACE FUNCTION dyn(p_name VARCHAR) 
RETURNS SETOF RECORD AS 
$$ 
    DECLARE 
    p_sql TEXT; 
    BEGIN 
    SELECT 'SELECT ' || 
    CASE p_name WHEN 'foo' THEN ' col1, col2, col3, col4 ' 
     WHEN 'bar' THEN 'col3, col4, col5, col6' 
     WHEN 'baz' THEN 'col1, col3, col4, col6' END || 
    ' FROM mytest' 
    INTO p_sql; 
    RETURN QUERY EXECUTE p_sql; 
    END 
$$ LANGUAGE 'plpgsql';

uso sería: SELECT * FROM dyn ('foo') AS (uno int, dos int, tres int, cuatro int)

Pero, sinceramente, sugiero solo hacer una vista para cada dispositivo.

+0

¿Quiere decir 'EJECUTAR 'SELECCIONAR'' no' SELECCIONAR' SELECCIONAR'' ¿verdad? –

+0

@ChrisTravers: esa línea simplemente concatena el script en 'p_sql'. Se ejecuta más abajo. –

+0

Ah, ya veo. ¿Alguna razón para no hacer simplemente RETURN QUERY EXECUTE 'SELECT ...'? –

0

Creo que su mayor problema es que tiene que devolver las filas de una forma que PostgreSQL puede entender. Esto significa básicamente que puede devolver un refcursor o puede devolver un conjunto coherente de tipos de datos. Prefiero lo último porque hace que el sistema sea un poco más consistente desde una perspectiva de programación y hay algunas instrucciones avanzadas que puedes tomar, pero también puedo ver lo contrario.

Cuestiones relacionadas