I'm using version 8.2 Postresql
Have been trying to do this for days now, and I keep hitting the same wall. How to Display the following:
Source Table || Source_column || Target View || Target Column
Stg_table1|| customerid || vw_customer || Customer_details_id
The biggest problem I have is that I can't link the Alias names in the view, back to the Source_column. This is because the Ordinal position of the columns in the Source_table, is different to the columns in the Target_view.
I have tried using these scripts, with no luck (this joins the columns back on using information schema, and Ordinal Position)
select distinct
a.attname AS SOURCE
, a.attname::information_schema.sql_identifier AS column_name
--, format_type(a.atttypid, NULL) AS Source_Type
, d.refobjid::regclass AS Source_table
, r.ev_class::regclass AS Target_View
--, pt.Typname AS TYPE, a.*
--, c.Column_name AS Target
--, c.Data_type
from pg_attribute as a
join pg_depend as d on d.refobjid = a.attrelid and d.refobjsubid = a.attnum
join pg_rewrite as r on d.objid = r.oid
--join information_schema.columns c ON a.attnum = c.ordinal_position --and r.ev_class::regclass = c.table_schema||'.'||c.table_name
--join pg_type as pt on a.atttypid = pt.oid
JOIN pg_class
ON pg_class.oid = a.attrelid
AND a.attnum > 0
where
r.ev_class = 'abc.vw_customer'::regclass
and c.table_schema||'.'||c.table_name = 'vw_customer';
And I have also tried it this way:
SELECT distinct dependent.relname, pg_attribute.attname
, pg_attrdef.*
--, pg_attribute.attname::information_schema.sql_identifier AS column_name
--, pg_depend.objid, pg_attribute.*
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependee ON pg_rewrite.ev_class = dependee.oid
JOIN pg_class as dependent ON pg_depend.refobjid = dependent.oid
JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
--AND pg_depend.refobjsubid = pg_attribute.attnum
LEFT JOIN pg_attrdef ON pg_attribute.attrelid = pg_attrdef.adrelid AND pg_attribute.attnum = pg_attrdef.adnum
WHERE dependee.relname = 'vw_customer'
--and attname in ('Customer_details_id', 'customerid')
AND pg_attribute.attnum > 0
Related
I'm trying to get indexes, primary keys, and all constraints for a schema in PostgreSQL using standard sql. Most of the posts I'm finding for how to do this use SQL syntax that is specific to PostgreSQL (I'd like to avoid this). This references include the following:
How do I get the primary key(s) of a table from Postgres via plpgsql?
https://wiki.postgresql.org/wiki/Retrieve_primary_key_columns
https://dba.stackexchange.com/questions/214863/how-to-list-all-constraints-of-a-table-in-postgresql
The following is what I am currently using. Do the queries shown below correctly query for the indexes, primary keys, and constraints for a given schema?
-- indexes
select
ns.nspname as schema,
t.relname as table_name,
i.relname as index_name,
a.attname as column_name,
ixs.indexdef as index_definition
from
pg_index ix
join pg_class i on ix.indexrelid = i.oid
join pg_class t on ix.indrelid = t.oid and t.relkind = 'r'
join pg_namespace ns on t.relnamespace = ns.oid
join pg_indexes ixs on 1=1
and ns.nspname = ixs.schemaname
and t.relname = ixs.tablename
and i.relname = ixs.indexname
join pg_attribute a on 1=1
and a.attrelid = t.oid
and a.attnum = any(ix.indkey)
where 1=1
and ns.nspname = 'webapi'
order by
1,2,3,4
;
-- primary keys
select
ns.nspname as schema,
t.relname as table_name,
i.relname as index_name,
a.attname as column_name,
ixs.indexdef as index_definition
from
pg_index ix
join pg_class i on ix.indexrelid = i.oid
join pg_class t on ix.indrelid = t.oid and t.relkind = 'r'
join pg_namespace ns on t.relnamespace = ns.oid
join pg_indexes ixs on 1=1
and ns.nspname = ixs.schemaname
and t.relname = ixs.tablename
and i.relname = ixs.indexname
join pg_attribute a on 1=1
and a.attrelid = t.oid
and a.attnum = any(ix.indkey)
where 1=1
and ix.indisprimary = true
and ns.nspname = 'webapi'
order by
1,2,3,4
;
-- constraints
select
ns.nspname as schema,
t.relname as table_name,
con.conname as constraint_name,
a.attname as column_name,
con.contype as constraint_type,
con.*
from
pg_constraint con
join pg_class t on con.conrelid = t.oid
join pg_namespace ns on t.relnamespace = ns.oid
join pg_attribute a on 1=1
and a.attrelid = t.oid
and a.attnum = any(con.conkey)
where 1=1
and ns.nspname = 'webapi'
order by
1,2,3,4
;
I maintain Beekeeper Studio, and one of it's functions is to display index information.
To get index information in Postgres I use the below query, but turns out this isn't compatible with Postgres < 9.4 because of the use of WITH ORDINALITY.
I'm really struggling to rewrite this in a way that would work for earlier versions. Hoping someone can offer some advice?
SELECT i.indexrelid::regclass AS indexname,
k.i AS index_order,
i.indexrelid as id,
i.indisunique,
i.indisprimary,
coalesce(a.attname,
(('{' || pg_get_expr(
i.indexprs,
i.indrelid
)
|| '}')::text[]
)[k.i]
) AS index_column,
i.indoption[k.i - 1] = 0 AS ascending
FROM pg_index i
CROSS JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS k(attnum, i)
LEFT JOIN pg_attribute AS a
ON i.indrelid = a.attrelid AND k.attnum = a.attnum
JOIN pg_class t on t.oid = i.indrelid
JOIN pg_namespace c on c.oid = t.relnamespace
WHERE
c.nspname = $1 AND
t.relname = $2
You can try this which has been tested in postgres 9.5, but not before :
SELECT i.indexrelid::regclass AS indexname,
k.i AS index_order,
i.indexrelid as id,
i.indisunique,
i.indisprimary,
coalesce(a.attname,
(('{' || pg_get_expr(
i.indexprs,
i.indrelid
)
|| '}')::text[]
)[k.i]
) AS index_column,
i.indoption[k.i - 1] = 0 AS ascending
FROM pg_index i
CROSS JOIN LATERAL (SELECT unnest(i.indkey), generate_subscripts(i.indkey, 1) + 1) AS k(attnum, i)
LEFT JOIN pg_attribute AS a
ON i.indrelid = a.attrelid AND k.attnum = a.attnum
JOIN pg_class t on t.oid = i.indrelid
JOIN pg_namespace c on c.oid = t.relnamespace
WHERE
c.nspname = $1 AND
t.relname = $2
How to list all constraints (Primary key, Foreign Key, check, unique mutual exclusive, ..) of a table in PostgreSQL?
Constraints of the table can be retrieved from catalog-pg-constraint. using the SELECT query.
SELECT con.*
FROM pg_catalog.pg_constraint con
INNER JOIN pg_catalog.pg_class rel ON rel.oid = con.conrelid
INNER JOIN pg_catalog.pg_namespace nsp ON nsp.oid = connamespace
WHERE nsp.nspname = '{schema name}'
AND rel.relname = '{table name}';
and the same can be viewed in PSQL using
\d+ {SCHEMA_NAME.TABLE_NAME}
Here is POSTGRES specific answer
..... it will retrive all columns and their relationship as well
SELECT * FROM (
SELECT
pgc.contype as constraint_type,
pgc.conname as constraint_name,
ccu.table_schema AS table_schema,
kcu.table_name as table_name,
CASE WHEN (pgc.contype = 'f') THEN kcu.COLUMN_NAME ELSE ccu.COLUMN_NAME END as column_name,
CASE WHEN (pgc.contype = 'f') THEN ccu.TABLE_NAME ELSE (null) END as reference_table,
CASE WHEN (pgc.contype = 'f') THEN ccu.COLUMN_NAME ELSE (null) END as reference_col,
CASE WHEN (pgc.contype = 'p') THEN 'yes' ELSE 'no' END as auto_inc,
CASE WHEN (pgc.contype = 'p') THEN 'NO' ELSE 'YES' END as is_nullable,
'integer' as data_type,
'0' as numeric_scale,
'32' as numeric_precision
FROM
pg_constraint AS pgc
JOIN pg_namespace nsp ON nsp.oid = pgc.connamespace
JOIN pg_class cls ON pgc.conrelid = cls.oid
JOIN information_schema.key_column_usage kcu ON kcu.constraint_name = pgc.conname
LEFT JOIN information_schema.constraint_column_usage ccu ON pgc.conname = ccu.CONSTRAINT_NAME
AND nsp.nspname = ccu.CONSTRAINT_SCHEMA
UNION
SELECT null as constraint_type , null as constraint_name , 'public' as "table_schema" ,
table_name , column_name, null as refrence_table , null as refrence_col , 'no' as auto_inc ,
is_nullable , data_type, numeric_scale , numeric_precision
FROM information_schema.columns cols
Where 1=1
AND table_schema = 'public'
and column_name not in(
SELECT CASE WHEN (pgc.contype = 'f') THEN kcu.COLUMN_NAME ELSE kcu.COLUMN_NAME END
FROM
pg_constraint AS pgc
JOIN pg_namespace nsp ON nsp.oid = pgc.connamespace
JOIN pg_class cls ON pgc.conrelid = cls.oid
JOIN information_schema.key_column_usage kcu ON kcu.constraint_name = pgc.conname
LEFT JOIN information_schema.constraint_column_usage ccu ON pgc.conname = ccu.CONSTRAINT_NAME
AND nsp.nspname = ccu.CONSTRAINT_SCHEMA
)
) as foo
ORDER BY table_name desc
I wasn't able to get the above solutions to work. Maybe they're no longer supported or more likely I'm doing something wrong. This is how I got it to work. Note that the "contype" column will be abbreviated with the constraint type (e.g. 'c' for check, 'p' for primary key, etc.). I include that variable in case you want to add a WHERE statement to filter for it after the FROM block.
select pgc.conname as constraint_name,
ccu.table_schema as table_schema,
ccu.table_name,
ccu.column_name,
contype,
pg_get_constraintdef(pgc.oid)
from pg_constraint pgc
join pg_namespace nsp on nsp.oid = pgc.connamespace
join pg_class cls on pgc.conrelid = cls.oid
left join information_schema.constraint_column_usage ccu
on pgc.conname = ccu.constraint_name
and nsp.nspname = ccu.constraint_schema
order by pgc.conname;
SELECT constraint_name, table_name, column_name, ordinal_position FROM information_schema.key_column_usage WHERE table_name = 'put your table name here';
I have a partitioned table out of main table using range.
CREATE TABLE public.partition1 PARTITION OF public.maintable
FOR VALUES FROM ('2017-01-01 00:00:00') TO ('2050-01-01 00:00:00')
How can i get the Values range information using a query to postgres.
I have used a query that at least gives me information for the main and partitioned tables, but i cannot seem to find a way to access the value range
FROM ('2017-01-01 00:00:00') TO ('2050-01-01 00:00:00')
assigned to table partition1
Query used to get partition table information
WITH RECURSIVE partition_info
(relid,
relname,
relsize,
relispartition,
relkind) AS
(
(SELECT oid AS relid,
relname,
pg_relation_size(oid) AS relsize,
relispartition,
relkind
FROM pg_catalog.pg_class
WHERE relname = 'completedorders' AND
relkind = 'p')
UNION ALL
(SELECT
c.oid AS relid,
c.relname AS relname,
pg_relation_size(c.oid) AS relsize,
c.relispartition AS relispartition,
c.relkind AS relkind
FROM partition_info AS p,
pg_catalog.pg_inherits AS i,
pg_catalog.pg_class AS c
WHERE p.relid = i.inhparent AND
c.oid = i.inhrelid AND
c.relispartition = true)
)
SELECT * FROM partition_info;
The following query provides the information about partitions as well. From there on its just string manipulation in order to get further information.
Note: you will have to change the name of the table in the query.
with recursive inh as (
select i.inhrelid, null::text as parent
from pg_catalog.pg_inherits i
join pg_catalog.pg_class cl on i.inhparent = cl.oid
join pg_catalog.pg_namespace nsp on cl.relnamespace = nsp.oid
where nsp.nspname = 'public' ---<< change table schema here
and cl.relname = 'tablename' ---<< change table name here
union all
select i.inhrelid, (i.inhparent::regclass)::text
from inh
join pg_catalog.pg_inherits i on (inh.inhrelid = i.inhparent)
)
select c.relname as partition_name,
n.nspname as partition_schema,
pg_get_expr(c.relpartbound, c.oid, true) as partition_expression,
pg_get_expr(p.partexprs, c.oid, true) as sub_partition,
parent,
case p.partstrat
when 'l' then 'LIST'
when 'r' then 'RANGE'
end as sub_partition_strategy
from inh
join pg_catalog.pg_class c on inh.inhrelid = c.oid
join pg_catalog.pg_namespace n on c.relnamespace = n.oid
left join pg_partitioned_table p on p.partrelid = c.oid
order by n.nspname, c.relname
What is the query to get the list all index names, its column name and its table name of a postgresql database?
I have tried to get the list of all indexes in a db by using this query but how to get the list of indexes, its column names and its table names?
SELECT *
FROM pg_class, pg_index
WHERE pg_class.oid = pg_index.indexrelid
AND pg_class.oid IN (
SELECT indexrelid
FROM pg_index, pg_class
WHERE pg_class.oid=pg_index.indrelid
AND indisunique != 't'
AND indisprimary != 't'
AND relname !~ '^pg_');
This will output all indexes with details (extracted from my view definitions):
SELECT i.relname as indname,
i.relowner as indowner,
idx.indrelid::regclass,
am.amname as indam,
idx.indkey,
ARRAY(
SELECT pg_get_indexdef(idx.indexrelid, k + 1, true)
FROM generate_subscripts(idx.indkey, 1) as k
ORDER BY k
) as indkey_names,
idx.indexprs IS NOT NULL as indexprs,
idx.indpred IS NOT NULL as indpred
FROM pg_index as idx
JOIN pg_class as i
ON i.oid = idx.indexrelid
JOIN pg_am as am
ON i.relam = am.oid;
Optionally add an extra join to the end so as to trim the namespaces:
SELECT i.relname as indname,
i.relowner as indowner,
idx.indrelid::regclass,
am.amname as indam,
idx.indkey,
ARRAY(
SELECT pg_get_indexdef(idx.indexrelid, k + 1, true)
FROM generate_subscripts(idx.indkey, 1) as k
ORDER BY k
) as indkey_names,
idx.indexprs IS NOT NULL as indexprs,
idx.indpred IS NOT NULL as indpred
FROM pg_index as idx
JOIN pg_class as i
ON i.oid = idx.indexrelid
JOIN pg_am as am
ON i.relam = am.oid
JOIN pg_namespace as ns
ON ns.oid = i.relnamespace
AND ns.nspname = ANY(current_schemas(false));
More human friendly version of #Denis solution:
SELECT
U.usename AS user_name,
ns.nspname AS schema_name,
idx.indrelid :: REGCLASS AS table_name,
i.relname AS index_name,
idx.indisunique AS is_unique,
idx.indisprimary AS is_primary,
am.amname AS index_type,
idx.indkey,
ARRAY(
SELECT pg_get_indexdef(idx.indexrelid, k + 1, TRUE)
FROM
generate_subscripts(idx.indkey, 1) AS k
ORDER BY k
) AS index_keys,
(idx.indexprs IS NOT NULL) OR (idx.indkey::int[] #> array[0]) AS is_functional,
idx.indpred IS NOT NULL AS is_partial
FROM pg_index AS idx
JOIN pg_class AS i
ON i.oid = idx.indexrelid
JOIN pg_am AS am
ON i.relam = am.oid
JOIN pg_namespace AS NS ON i.relnamespace = NS.OID
JOIN pg_user AS U ON i.relowner = U.usesysid
WHERE NOT nspname LIKE 'pg%'; -- Excluding system tables
The Query to list all the indexes of a database
SELECT
tablename,
indexes [1],
indexes [2],
indexes [3],
indexes [4],
indexes [5],
indexes [6],
indexes [7],
indexes [8],
indexes [9],
indexes [10]
FROM (SELECT
tablename,
array_agg(indexname) AS indexes
FROM pg_indexes
WHERE schemaname = 'public'
GROUP BY tablename) as sub;
Here's a version that simplifies things compared to other answers by
avoiding nested selects
avoiding built-in functions (maybe hard to remember)
using LATERAL and UNNEST(...) WITH ORDINALITY features available in later PostgreSQL versions (9.4+)
SELECT
tnsp.nspname AS schema_name,
trel.relname AS table_name,
irel.relname AS index_name,
array_agg (
a.attname
|| ' ' || CASE o.option & 1 WHEN 1 THEN 'DESC' ELSE 'ASC' END
|| ' ' || CASE o.option & 2 WHEN 2 THEN 'NULLS FIRST' ELSE 'NULLS LAST' END
ORDER BY c.ordinality
) AS columns
FROM pg_index AS i
JOIN pg_class AS trel ON trel.oid = i.indrelid
JOIN pg_namespace AS tnsp ON trel.relnamespace = tnsp.oid
JOIN pg_class AS irel ON irel.oid = i.indexrelid
CROSS JOIN LATERAL unnest (i.indkey) WITH ORDINALITY AS c (colnum, ordinality)
LEFT JOIN LATERAL unnest (i.indoption) WITH ORDINALITY AS o (option, ordinality)
ON c.ordinality = o.ordinality
JOIN pg_attribute AS a ON trel.oid = a.attrelid AND a.attnum = c.colnum
GROUP BY tnsp.nspname, trel.relname, irel.relname
If you are also interested in index size, you may use this query from the PostgreSQL Wiki.
SELECT
t.tablename,
indexname,
c.reltuples AS num_rows,
pg_size_pretty(pg_relation_size(quote_ident(t.tablename)::text)) AS table_size,
pg_size_pretty(pg_relation_size(quote_ident(indexrelname)::text)) AS index_size,
CASE WHEN indisunique THEN 'Y'
ELSE 'N'
END AS UNIQUE,
idx_scan AS number_of_scans,
idx_tup_read AS tuples_read,
idx_tup_fetch AS tuples_fetched
FROM pg_tables t
LEFT OUTER JOIN pg_class c ON t.tablename=c.relname
LEFT OUTER JOIN
( SELECT c.relname AS ctablename, ipg.relname AS indexname, x.indnatts AS number_of_columns, idx_scan, idx_tup_read, idx_tup_fetch, indexrelname, indisunique FROM pg_index x
JOIN pg_class c ON c.oid = x.indrelid
JOIN pg_class ipg ON ipg.oid = x.indexrelid
JOIN pg_stat_all_indexes psai ON x.indexrelid = psai.indexrelid )
AS foo
ON t.tablename = foo.ctablename
WHERE t.schemaname='public'
ORDER BY 1,2;
For Non-Composite Indexes
select t.relname,i.relname ,
STRING_AGG(pga.attname||'', ','order by i.relname,pga.attnum) as columnName
from pg_class t inner join pg_index ix
on t.oid = ix.indrelid
inner join pg_class i
on i.oid = ix.indexrelid
inner join pg_attribute pga
on
pga.attrelid = i.oid
inner join pg_indexes pgidx
on pgidx.indexname=i.relname
where
t.relkind = 'r'
and pgidx.schemaname='asit_cm'
and t.relname ='accessory'
group by t.relname,i.relname having count(*)=1
For Composite Indexes
select t.relname,i.relname ,
STRING_AGG(pga.attname||'', ','order by i.relname,pga.attnum) as columnName
from pg_class t inner join pg_index ix
on t.oid = ix.indrelid
inner join pg_class i
on i.oid = ix.indexrelid
inner join pg_attribute pga
on
pga.attrelid = i.oid
inner join pg_indexes pgidx
on pgidx.indexname=i.relname
where
t.relkind = 'r'
and pgidx.schemaname='asit_cm'
and t.relname ='accessory'
group by t.relname,i.relname having count(*)=1