2011-03-03 18 views
6

¿Cómo puedo obtener la etiqueta de cada columna en un conjunto de resultados para anteponer el nombre si su tabla?¿Prefijo el nombre de la tabla a cada columna en un conjunto de resultados en SQL? (Postgres específicamente)

Quiero que esto suceda para las consultas en tablas individuales, así como las uniones.

Ejemplo:

SELECT first_name, last_name FROM person; 

Quiero que los resultados sean:

| person.first_name | person.last_name | 
|-------------------|------------------| 
| Wendy    | Melvoin   | 
| Lisa    | Coleman   | 

podría utilizar "AS" para definir un alias para cada columna, pero que sería tedioso. Quiero que esto suceda automáticamente.

SELECT first_name AS person.first_name, last_name AS person.last_name FROM person; 

El motivo de mi pregunta es que estoy usando un controlador de base de datos que no proporciona los metadatos informándome la columna de la base de datos desde donde el conjunto de resultados obtuvo sus datos. Estoy tratando de escribir código genérico para manejar el conjunto de resultados.

Me gustaría saber cómo hacer esto en SQL en general, o al menos en Postgres específicamente.

SQLite tenía esa característica, aunque veo que ahora está inexplicablemente obsoleta. SQLite tiene dos configuraciones de pragma: full_column_names & short_column_names.

+1

no creo que esto es posible. –

+0

Al ver cómo SQLAlchemy hace todo esto "manualmente", yo también dudo que esto se pueda hacer. –

+2

Una razón por la que esto es imposible es porque no hay nada que relacione mágicamente una columna de resultados con una tabla. El resultado en su columna puede ser una expresión hecha de 0 o más columnas (y 0 o más tablas). El nombre de columna predeterminado para el resultado a menudo se toma prestado de un nombre de columna, pero también puede provenir de un nombre de función (es decir, 'SELECT min (x)' devuelve una columna llamada 'min' de forma predeterminada) y puede ser ' ?¿columna?' cuando no hay un defecto Creo que su (lamentablemente tediosa) sugerencia de usar 'AS' es la única respuesta, salvo la piratería y la recompilación de Postgres con un comportamiento diferente. – Flimzy

Respuesta

15

Sé que esta pregunta es un poco antigua, pero tal vez alguien tropezará con la respuesta y les ayudará.

La forma correcta de hacer lo que está buscando es crear y usar una Vista. Sí, será un poco tedioso por una sola vez escribir todos esos nuevos nombres de columna como alias, pero si hay muchas columnas aquí hay un truco que puede usar para aprovechar los metadatos de PostgreSQL para escribir el texto de la vista:

select 'CREATE OR REPLACE VIEW people AS SELECT ' || 
(select string_agg(column_name || ' AS person_' || column_name, ', ') 
from information_schema.columns 
where table_name = 'person' 
group by table_name) || 
' FROM person;'; 

ejecutan rendimientos esto:

?column?             
------------------------------------------------------------------------------------------------------------- 
CREATE OR REPLACE VIEW people AS SELECT last_name AS person_last_name, first_name AS person_first_name FROM person; 

1 record(s) selected [Fetch MetaData: 0/ms] [Fetch Data: 0/ms] 
[Executed: 4/21/12 2:05:21 PM EDT ] [Execution: 9/ms] 

continuación, puede copiar y ejecutar los resultados y voilá:

select * from people; 

person_last_name  person_first_name  
------------------- -------------------- 
Melvoin    Wendy     
Coleman    Lisa     

2 record(s) selected [Fetch MetaData: 1/ms] [Fetch Data: 0/ms] 
+0

Solución muy inteligente. –

+0

¡Esto es muy inteligente, de hecho! –

+0

¿Es posible ejecutar esto en una sola declaración? Porque ahora necesita dos viajes de ida y vuelta. Tal vez use algo como 'EXECUTE', pero funciona solo en funciones. – davekr

4

Para obtener el VIEW (Daryl's idea) en un sola declaración utilizar una función o un DO command con EXECUTE:

DO 
$do$ 
BEGIN 

EXECUTE (
    SELECT format(
     'CREATE TEMP VIEW people AS SELECT %s FROM %I' 
    , string_agg(format('%I AS %I', attname, attrelid::regclass || '.' || attname), ', ') 
    , attrelid::regclass) 
    FROM pg_attribute 
    WHERE attrelid = 'person'::regclass -- supply source table name once 
    AND attnum > 0 
    AND NOT attisdropped 
    GROUP BY attrelid 
    ); 

END 
$do$; 

Esto se ejecuta inmediatamente una orden de la forma:

CREATE OR REPLACE VIEW people AS 
SELECT person_id AS "person.person_id" 
    , first_name AS "person.first_name" 
    , last_name AS "person.last_name" 
FROM person; 

sería menos problemas para concatenar nombres de columna legales con ' _' en lugar de '.'. Pero debe estar preparado para los nombres no estándar que requieren doble cotización (y defenderse contra una posible inyección SQL) de todos modos.

Opcionalmente, puede proporcionar un nombre de tabla con esquema calificado (myschema.person). El nombre del esquema tiene el prefijo en los nombres de columna automáticamente si está fuera del actual search_path.

Para un uso repetido, ajuste esto en una función plpgsql y haga que el nombre de la tabla sea un parámetro text. Toda la conversión de texto a código se desinfecta aquí para evitar la inyección de SQL. Ejemplo con más información aquí:

Y es posible utilizar el nuevo to_regclass() en Postgres 9.4+:

Cuestiones relacionadas