How to list the columns of a view in Postgres? - sql

For a physical table, I have been using the following SQL:
select column_name, data_type, character_maximum_length
from INFORMATION_SCHEMA.COLUMNS
where table_name = 'a_table_name'
I found that this doesn't work for a view. Is there a way to get the schema of a view by running a SQL command (not via psql).

Postgres has dedicated System Catalog Information Functions to help with that.
To get the full view definition:
SELECT pg_get_viewdef('public.view_name');
Schema-qualification is optional. If no schema is prefixed, the current search_path setting decides visibility.
A quick hack would be to just:
SELECT * FROM public.view_name LIMIT 0;
Depending on your client, column names and types should still be displayed. Or LIMIT n to get some sample values, too. The underlying query is actually executed then (unlike with LIMIT 0).
To list columns and their data type, in order, you might base the query on pg_attribute:
SELECT attname AS column_name, format_type(atttypid, atttypmod) AS data_type
FROM pg_attribute
WHERE attrelid = 'public.view_name'::regclass
-- AND NOT attisdropped
-- AND attnum > 0
ORDER BY attnum;
Type modifiers like maximum length are included in data_type this way.
Internally, a VIEW is implemented as special table with a rewrite rule. Details in the manual here. The table is saved in the system catalogs much like any regular table.
About the cast to regclass:
How to check if a table exists in a given schema
The same query works for tables or materialized views as well. Uncomment the additional filters above to only get visible user columns for tables.

SELECT
a.attname,
t.typname,
a.atttypmod
FROM pg_class c
INNER JOIN pg_attribute a ON a.attrelid = c.oid
INNER JOIN pg_type t ON t.oid = a.atttypid
WHERE c.relkind = 'v'
AND c.relname = 'put_viewname_here';
ATTENTION: Since the viewname is unique only in the schema, you might also want to add an INNER JOIN to pg_namespace and add a condition to the where-clause.
For the first version of your question:
SELECT n.nspname
FROM pg_class c
INNER JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'v'
AND c.relname = 'put_viewname_here';
ATTENTION: This might give you multiple schemas, since a viewname is only unique inside a schema and thus a viewname does not always identify one view.

Related

Query to get schema names in Postgres

I need a logical / cleaner query to get all the schema names that I have created
select schema_name
from "information_schema"."schemata"
AND
SELECT nspname
FROM pg_catalog.pg_namespace;
Returns a superset of schema names that have system created schema which I don't need.
I just want the schema names that I have created.
Try filtering from information_schema.schemata the pg_* schemas and the information_schema itself:
SELECT * from information_schema.schemata
WHERE NOT schema_name LIKE 'pg_%' AND schema_name <> 'information_schema'
Excluding the schemas owned by postgres, as suggested by Gordon, works only with the condition that postgres isn't the owner of any other schema but the system schemas. In case you created a schema with the user postgres, it will be excluded from the result set.
If you don't want the built-in schemas, then use:
select schema_name
from "information_schema"."schemata"
where schema_owner <> 'postgres';
If you want the ones that you specifically created, then check for the ones where you are the owner.
select
*,
nspowner::regrole as role_name
from pg_namespace
where nspowner = 'postgres'::regrole;
returns all schemes where owner is postgres user. Change it to your user name to get schemes owned by you.
https://www.postgresql.org/docs/current/datatype-oid.html
Below query solved my problem
SELECT distinct pg_namespace.nspname
FROM pg_catalog.pg_inherits INNER JOIN
pg_catalog.pg_class ON (pg_inherits.inhrelid = pg_class.oid) INNER JOIN
pg_catalog.pg_namespace ON (pg_class.relnamespace = pg_namespace.oid)
WHERE pg_namespace.nspname <> 'public';

Translating query from Firebird to PostgreSQL

I have a Firebird query which I should rewrite into PostgreSQL code.
SELECT TRIM(RL.RDB$RELATION_NAME), TRIM(FR.RDB$FIELD_NAME), FS.RDB$FIELD_TYPE
FROM RDB$RELATIONS RL
LEFT OUTER JOIN RDB$RELATION_FIELDS FR ON FR.RDB$RELATION_NAME = RL.RDB$RELATION_NAME
LEFT OUTER JOIN RDB$FIELDS FS ON FS.RDB$FIELD_NAME = FR.RDB$FIELD_SOURCE
WHERE (RL.RDB$VIEW_BLR IS NULL)
ORDER BY RL.RDB$RELATION_NAME, FR.RDB$FIELD_NAME
I understand SQL, but have no idea, how to work with this system tables like RDB$RELATIONS etc. It would be really great if someone helped me with this, but even some links with this tables explanation will be OK.
This piece of query is in C++ code, and when I'm trying to do this :
pqxx::connection conn(serverAddress.str());
pqxx::work trans(conn);
pqxx::result res(trans.exec(/*there is this SQL query*/));//and there is a mistake
it writes that:
RDB$RELATIONS doesn't exist.
Postgres has another way of storing information about system content. This is called System Catalogs.
In Firebird your query basically returns a row for every column of a table in every schema with an additional Integer column that maps to a field datatype.
In Postgres using system tables in pg_catalog schema something similar can be achieved using this query:
SELECT
TRIM(c.relname) AS table_name, TRIM(a.attname) AS column_name, a.atttypid AS field_type
FROM pg_class c
LEFT JOIN pg_attribute a ON
c.oid = a.attrelid
AND a.attnum > 0 -- only ordinary columns, without system ones
WHERE c.relkind = 'r' -- only tables
ORDER BY 1,2
Above query does return system catalogs as well. If you'd like to exclude them you need to add another JOIN to pg_namespace and a where clause with pg_namespace.nspname <> 'pg_catalog', because this is the schema where system catalogs are stored.
If you'd also like to see datatype names instead of their representative numbers add a JOIN to pg_type.
Information schema consists of collection of views. In most cases you don't need the entire SQL query that stands behind the view, so using system tables will give you better performance. You can inspect views definition though, just to get you started on the tables and conditions used to form an output.
I think you are looking for the information_schema.
The tables are listed here: https://www.postgresql.org/docs/current/static/information-schema.html
So for example you can use:
select * from information_schema.tables;
select * from information_schema.columns;

PostgreSQL: getting all functions related to table

I have this function:
SELECT n.nspname AS schema_name
,p.proname AS function_name
,pg_get_function_arguments(p.oid) AS args
,pg_get_functiondef(p.oid) AS func_def
FROM (SELECT oid, * FROM pg_proc p WHERE NOT p.proisagg) p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname !~~ 'pg_%'
AND n.nspname <> 'information_schema'
AND pg_get_functiondef(p.oid) ~ '\mTableName\M';
it gives me a list of functions that uses TableName. However it doesn't ignore notes. For example if in function A there will be a line like:
-- select * from TableName
it will show A in the result even though its a note and A doesn't really uses TableName.
How can I make a query that does the same thing but ignore all notes?
You may find everything you need directly on this wiki page : https://wiki.postgresql.org/wiki/Pg_depend_display
There is all sorts of dependency views depending on you PostgreSQL version.

What select query will list domains within Postgres?

I'm aware of the psql command that will list these, but I'm attempting to write an extension for Oracle's SQL Developer that will list them on the left-hand navigator panel. The XML format requires a select statement.
For example purposes, I'll include the code I cooked up for sequences:
<sql constrained="true">
<![CDATA[SELECT relname FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace WHERE relkind = 'S' AND nspname = :SCHEMA]]>
</sql>
I've attempted to figure it out for myself, but I don't see anything with my test domain names in pg_class or any other of those internal tables (though it must be in one, somewhere).
Does anyone have a hint?
Asked too soon... here's a select query that will return domains from a specific schema:
SELECT typname FROM pg_catalog.pg_type JOIN pg_catalog.pg_namespace ON pg_namespace.oid = pg_type.typnamespace WHERE typtype = 'd' AND nspname = 'someschema'
Minor tweaking can also return enums, ranges, and composites/rows. More information in the docs.

Can I select a field from data type?

Can I select a field/column from data type?
Postgres 7.4 (yep we are upgrading)
SELECT *
FROM tbl_name
WHERE tbl_name.column = 'timestamp with time zone'
That requires metadata.
select column_name
from information_schema.columns
where table_schema='your_schema'
and table_name='tbl_name'
and data_type='timestamp without time zone'
order by ordinal_position;
ETA: If you want the actual data from the table with column names matching the list above, you could probably set up a user-defined function that would grab those column names, put them in a comma-delimited list, and parse the query from tbl_name appropriately (of course, this is a lot easier if you're working in a scripting language slightly outside of the database).
I had to do that recently. To ease things I defined two views :
CREATE VIEW view_table_columns AS
SELECT n.nspname AS schema, cl.relname AS table_name,
a.attname AS column_name, ty.typname AS data_type,
a.attnotnull AS nnull,
a.atthasdef AS hasdef,
descr.description AS descr, cl.oid AS tableoid, a.attnum AS colnum
FROM pg_attribute a
JOIN pg_class cl ON a.attrelid = cl.oid AND cl.relkind = 'r'::"char"
JOIN pg_namespace n ON n.oid = cl.relnamespace
JOIN pg_type ty ON ty.oid = a.atttypid
LEFT JOIN pg_description descr
ON descr.objoid = cl.oid AND descr.objsubid = a.attnum
WHERE a.attnum > 0 AND NOT a.attisdropped
AND n.nspname !~~ 'pg_%'::text
AND n.nspname <> 'information_schema'::name;
COMMENT ON VIEW view_table_columns IS 'Lista all fields of all tables';
CREATE VIEW view_table_columns2 AS
SELECT view_table_columns.*,
( SELECT count(*) AS count
FROM pg_index
WHERE pg_index.indrelid = pg_index.tableoid AND
(view_table_columns.colnum = ANY (pg_index.indkey::smallint[]))) AS indexes
FROM view_table_columns;
COMMENT ON VIEW view_table_columns2 IS 'Adds to view_table_columns info about indexed fields';
That includes, for every field in your tables the following info:
schema name
table name
column name
data_type name
is nullable?
has default value?
description (comment)
tableoid (handy if you need to get more data from catalog)
column number (idem)
indexes (in second view - number of indexes that refer to this column)