I'm working on PostreSQL and I have this code to select all the tables and their columns from my database
select t.table_name
, array_agg(c.column_name::text) as columns
from information_schema.tables t
join information_schema.columns c
on t.table_name = c.table_name
where t.table_schema = 'public'
and t.table_type = 'BASE TABLE'
and c.table_schema = 'public'
group
by t.table_name;
I'm trying to modify it to give me only the tables that contains specific column name e.g 'email'
The problem is that when I'm adding another "and" it only returns one column instead of all
where t.table_schema = 'public' and t.table_type= 'BASE TABLE' and c.table_schema = 'public' and c.column_name = 'email'
Use a having clause:
select t.table_name
, array_agg(c.column_name::text) as columns
from information_schema.tables t
join information_schema.columns c
on t.table_name = c.table_name
and t.table_schema = c.table_schema
where t.table_schema = 'public'
and t.table_type = 'BASE TABLE'
group by t.table_name
having 'email' = any(array_agg(c.column_name::text))
If you want to check for multiple columns you could do that like this:
select t.table_name
, array_agg(c.column_name::text) as columns
from information_schema.tables t
join information_schema.columns c
on t.table_name = c.table_name
and t.table_schema = c.table_schema
where t.table_schema = 'public'
and t.table_type = 'BASE TABLE'
group by t.table_name
having array_agg(c.column_name::text) #> array['email', 'phone']
Related
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';
For the following TSQL, the expectation is to generate and output where COL is nested inside T, but returns a flat result.
With FilteredTables as (
select * from INFORMATION_SCHEMA.TABLES
union
select * from INFORMATION_SCHEMA.TABLES -- Repeated just to show the issue
)
select T.TABLE_SCHEMA, T.TABLE_NAME,
COL.COLUMN_NAME, --as "columns.name",
COL.DATA_TYPE --as "columns.type"
from FilteredTables T
INNER JOIN INFORMATION_SCHEMA.COLUMNS COL
on T.TABLE_SCHEMA = COL.TABLE_SCHEMA
and T.TABLE_NAME = COL.TABLE_NAME
--order by [Schema], [Table]
FOR XML Auto
When the union is removed from the FilteredTables CTE it works as expected
Is this a SQL Bug or is there any good reason for this?
In case a Union is required instead of using FROM cte_name, use FROM (SELECT * FROM cte_name)
With FilteredTables as (
select * from INFORMATION_SCHEMA.TABLES
union
select * from INFORMATION_SCHEMA.TABLES -- Repeated just to show the issue
)
select T.TABLE_SCHEMA, T.TABLE_NAME,
COL.COLUMN_NAME, --as "columns.name",
COL.DATA_TYPE --as "columns.type"
from
-- Workaround
(SELECT * FROM FilteredTables) T
INNER JOIN INFORMATION_SCHEMA.COLUMNS COL
on T.TABLE_SCHEMA = COL.TABLE_SCHEMA
and T.TABLE_NAME = COL.TABLE_NAME
--order by [Schema], [Table]
FOR XML Auto
I am using PGAdmin for executing a query , If there is 30 tables in database and one column XYZ is used in min 10 to 15 table So, how can i get the tables in which that particular column is used.
Kindly help me out
You can use the information_schema views:
select table_schema,
table_name
from information_schema.columns
where column_name = 'xyz';
Just right click on your schema then you will find a option search objects.
Click on the option and select the option you want to search from the new opened window.
Now fill the pattern as name or as per the option you have selected with prefix and suffix as "%".
select t.table_schema,
t.table_name
from information_schema.tables t
inner join information_schema.columns c on c.table_name = t.table_name
and c.table_schema = t.table_schema
where c.column_name = 'last_name'
and t.table_schema not in ('information_schema', 'pg_catalog')
and t.table_type = 'BASE TABLE'
order by t.table_schema;
Replace that 'last_name' with your column XYZ
Thanks
Just override the "column_x" for your desired column:
> select t.table_schema,
> t.table_name from information_schema.tables t inner join information_schema.columns c on c.table_name = t.table_name
> and c.table_schema = t.table_schema where c.column_name = 'column_x'
> and t.table_schema not in ('information_schema', 'pg_catalog')
> and t.table_type = 'BASE TABLE' order by t.table_schema;
Original from https://dataedo.com/kb/query/postgresql/find-tables-with-specific-column-name
just do the right-click on the databases list, refresh, schemas, public, tables
When I was learning pgadmin and postgresql, I found this tool helpful, as it allows to play with the ui
http://choose.tools/tool
I'm using redshift and would like to create a comma separated list of columns. I'm trying to grab the column names from information schema using listagg:
SELECT
listagg(column_name,',') within group (order by ordinal_position)
FROM information_schema.columns
WHERE table_schema = 'my_schema'
AND table_name = 'my table';
I'm getting the following error:
[Amazon](500310) Invalid operation: Function (listagg(text,text)) must be applied on at least one user created tables;
Here is a work around I tested..
select listagg(column_name, ', ') within group (order by column_name)
from
(
select
a.attname::varchar as column_name, typname::varchar as data_type
from
pg_type t,
pg_attribute a,
pg_class c,
pg_namespace ns,
(select top 1 1 from my_schema.my_table)
where
t.oid=a.atttypid
and a.attrelid = c.oid
and c.relnamespace = ns.oid
and typname NOT IN ('oid','xid','tid','cid')
and attname not in ('deletexid', 'insertxid')
and trim(relname) = 'my_table'
and ns.nspname = 'my_schema'
)
Although this does not answer how to apply listagg on information_schema, I can recommend an alternative method of using listagg on the pg catalog tables instead.
Try this:
SELECT DISTINCT listagg(attname, ',') WITHIN GROUP (ORDER BY a.attsortkeyord) AS "columns"
FROM pg_attribute a, pg_namespace ns, pg_class c, pg_type t, stv_tbl_perm p, pg_database db
WHERE t.oid=a.atttypid AND a.attrelid=p.id AND ns.oid = c.relnamespace AND db.oid = p.db_id AND c.oid = a.attrelid
AND typname NOT IN ('oid','xid','tid','cid')
AND ns.nspname = 'my_schema'
AND RTRIM(name) = 'my table'
I have query in DB2 to get table definition / structure
SELECT c.column_name,
c.column_default,
c.data_type,
t.table_name,
c.character_maximum_length AS LENGTH
FROM sysibm.tables t
JOIN sysibm.columns c
ON t.table_schema = c.table_schema
AND t.table_name = c.table_name
WHERE t.table_schema = SCHEMA
AND t.table_name = TABLE NAME
IN this I want to get column type is Isnullable true or false.
Can any one please help?
There should be a column, IS_NULLABLE , in the sysibm.columns table.