2011-03-20 15 views
5

Hay mucha información que se puede recuperar de information_schema y pg_catalog en postgresql. Me gustaría recuperar información sobre columnas indexadas por un índice determinado, similar a lo que alcanzaría con pragma index_info(<index_name>) en sqlite3. ¿Cómo se puede lograr esto sin analizar la declaración create index?postgresql: ¿cómo lista columnas indexadas?

+0

@OMG Ponies: Porque la respuesta no es tan simple como parece. – intgr

Respuesta

7

Esas cosas son bastante fáciles de descubrir.

Simplemente ejecute psql con la opción -E y le mostrará las instrucciones SQL que se utilizan. Así que cuando se ejecuta \ d index_name la siguiente declaración (entre otros) se utiliza para recuperar las columnas de índice:

 
SELECT a.attname, 
     pg_catalog.format_type (a.atttypid,a.atttypmod), 
     (SELECT SUBSTRING (pg_catalog.pg_get_expr (d.adbin,d.adrelid) FOR 128) 
     FROM pg_catalog.pg_attrdef d 
     WHERE d.adrelid = a.attrelid 
     AND d.adnum = a.attnum 
     AND a.atthasdef)a.attnotnull, 
     a.attnum, 
     pg_catalog.pg_get_indexdef (a.attrelid,a.attnum,TRUE) AS indexdef 
FROM pg_catalog.pg_attribute a 
WHERE a.attrelid = (SELECT oid FROM pg_class WHERE relname = 'index_name') 
AND a.attnum > 0 
AND NOT a.attisdropped 
ORDER BY a.attnum; 
+0

No tenía idea de que puede mostrar una información de índice con '\ d'. Eso es muy útil, así como la opción '-E'. Muchas gracias. – gruszczy

0

respuesta aceptada no funcionó para mí (error ocurrió en la ejecución).

De todos modos, puede listar todas las columnas de la base de datos y marcar todos los indexadas en algunas columnas manera (habilidades para limitar el conjunto de filas resultado se mencionan como los comentarios):

WITH 
    table_select as (
     select row_number() over(ORDER BY relname) as rownum, 
     c.relname, c.oid, c.reltuples 
     FROM pg_class c 
     JOIN pg_namespace n ON (n.oid = c.relnamespace) 
     WHERE c.relkind = 'r'::"char" 
       --AND n.nspname = '%MyNameSpaceHere%' 
     ORDER BY c.relname  
    ), 
    indxs as (
    select distinct t.relname as table_name, a.attname as column_name 
    from pg_class t, pg_class i, pg_index ix, pg_attribute a 
    where 
     t.oid = ix.indrelid 
     and i.oid = ix.indexrelid 
     and a.attrelid = t.oid 
     and a.attnum = ANY(ix.indkey) 
     and t.relkind = 'r' 
     --and t.relname like 'mytable here' 
     and cast (i.oid::regclass as text) like '%MyNameSpaceHere%' 
    order by 
     t.relname --, i.relname 
    ), 
    cols as (
    select a.attname, a.attrelid, c.oid, col.TABLE_NAME, col.COLUMN_NAME 
     FROM table_select c 
     JOIN pg_attribute a ON (a.attrelid = c.oid) AND (a.attname <> 'tableoid') 
     LEFT JOIN information_schema.columns col ON 
(col.TABLE_NAME = c.relname AND col.COLUMN_NAME = a.attname) 
     WHERE  
      (a.attnum >= 0) --attnum > 0 for real columns 
    ) 

    --select * from table_select t 
    select c.TABLE_NAME, c.COLUMN_NAME, 
     case when i.column_name is not null then 'Y' else '' end as is_indexed 
    from cols c 
    left join indxs i on (i.table_name = c.table_name and i.column_name = c.column_name) 

El resultado ejemplo:

table_name column_name is_indexed 
    'events  id   "Y" 
    events  type   "Y" 
    events  descr   "" ' 
Cuestiones relacionadas