Metadata from a postgresql-database - postgresql

I want to get data about all relationships from a PostgreSql-database with query like
SELECT
[creatorUser].[primTableName].[primColumnName] AS primary_column,
[creatorUser].[foreignTableName].[foreignColumnName] AS foreign_column,
FROM
sys.sysidx si,
sysidxcol sic,
sys.SYSFKCOL sfc,
sysusers su,
sys.systable st,
sys.syscolumn sc
WHERE
si.table_id=sic.table_id AND
si.index_id=sic.index_id AND
sfc.primary_column_id=sic.primary_column_id AND
sfc.foreign_table_id=sic.table_id AND
st.table_id=sfc.foreign_table_id AND
su.uid=st.creator AND
sc.column_name=si.index_name
Can anybody help, how to get that data? How to be a correct query
owner1.table1.primCol1 owner1.table1.foreignCol1
owner1.table1.primCol2 owner1.table1.foreignCol2
..
?

PostgreSQL has no sys tables, so it's not clear how you could possibly expect that query to work. Given your comments, I'm guessing that's the query you use on Sybase, and you want to translate it for PostgreSQL.
Well, assuming that the Sybase syntax:
[creatorUser].[primTableName].[primColumnName] AS primary_column,
[creatorUser].[foreignTableName].[foreignColumnName] AS foreign_column,
means "Concatenate the user who created the relationship, the table name, and the column name" I'd probably do something in PostgreSQL like:
SELECT
format('%I.%I.%I', fk.table_schema, fk.table_name, fk.column_name) AS foreign_side,
format('%I.%I.%I', pk.table_schema, pk.table_name, pk.column_name) AS target_side
FROM
information_schema.referential_constraints rc
INNER JOIN information_schema.key_column_usage fk
ON (rc.constraint_catalog = fk.constraint_catalog
AND rc.constraint_schema = fk.constraint_schema
AND rc.constraint_name = fk.constraint_name)
INNER JOIN information_schema.constraint_column_usage pk
ON (rc.unique_constraint_catalog = pk.constraint_catalog
AND rc.unique_constraint_schema = rc.constraint_schema
AND rc.unique_constraint_name = pk.constraint_name);
Except for the format(...) that'll work on Sybase too, with some luck.
Output like:
foreign_side | target_side
---------------------+---------------------------------
public.users.id_cat | public.usercategories.id_numcat
(1 row)
That's schema.table.column . I'm guessing Sybase's "creatorUser" is really "schema" in this case.

You should query appropriate tables under pg_catalog or information_schema schemas. The easiest way to figure out the correct query is to run (... = other command-line options like user, database, ...)
psql -E ...
and then psql displays meta-data queries used in internal commands like \d, \dt, \dv, ... From manual:
-E
--echo-hidden
Echo the actual queries generated by \d and other backslash commands. You can use this to study psql's internal operations. This is equivalent to setting the variable ECHO_HIDDEN from within psql.
information_schema is same as pg_catalog but more portalbe (it is defined in SQL standard). If your app uses postgres only then I would use pg_catalog instead of information_schema

Related

Find a table in a schema without knowing in advance

Is it possible to easily see what tables exist in what schemas, at a glance?
So far I have had to connect to a database, view the schemas, then change the search path to one of the schemas and then list the tables. I had to do this for multiple schemas until I found the table I was looking for.
What if there is a scenario where you inherit a poorly documented database and you want to find a specific table in hundreds of schemas?
Ideally I imagine some output like so;
SCHEMA TABLE
--------------------
schema1 table1
schema2 table2
schema2 table1
--------------------
Or even the more standard <SCHEMA_NAME>.<TABLE_NAME>;
schema1.table1
schema2.table2
schema2.table1
The latter output would be even better since you could simply check the table using copy-paste;
my-database=# \d schema2.table1
Ideally I'm hoping I missed a built-in command to find this. I don't really want to create and memorize a lengthy SQL command to get this (somewhat basic) information.
You can make use of pg_tables
SELECT schemaname, tablename,
quote_ident(schemaname) || '.' || quote_ident(tablename)
FROM pg_tables
WHERE tablename = 'test';

Select all tables in psql database EXCEPT those matching [pattern]

I have a database with many tables that are used as a reference for valid values in the other tables. These reference tables are all named valid[table], so I can display them in psql with \dt valid*.
I'd like to be able to select all the non-reference tables (which are more variably named, but none of them start with valid), but can't figure out how. I've tried various things like \dt !valid* , \dt !~valid* , \dt NOT LIKE 'valid%', but these either error or don't find a match.
Any suggestions would be appreciated!
According to the manual, psql supports these patterns. Normally you could use regular expression negative lookahead (?!valid)* but ? cannot be used in regular expression with psql because it is translated to .. It is probably easier to do a query from INFROMATION SCHEMA:
SELECT table_name FROM information_schema.tables
WHERE table_schema NOT IN ('pg_catalog', 'information_schema') --exclude system tables
AND table_type = 'BASE TABLE' -- only tables
AND table_name NOT LIKE 'valid%';

How do I grant select for a user on all tables?

I have a user in my DB2 database that I want to grant select rights on all tables and views for a given schema. Any thoughts on how to do that as one SQL statement?
In order to grant select to a given user, you have to "generate" the sentence for each table and view of a given schema. You can do it via the CLP with a query like this:
db2 -x "select 'grant select on table ' || rtrim(tabschema) || '.' || rtrim(tabname) || ' to user JOHN_DOE' from syscat.tables where tabschema like 'FOO%' and (type = 'T' or type = 'V')" | db2 +p -tv
This command line will generate the grants for user JOHN_DOE for all tables (T) and views (V) of any schema starting with FOO.
If you have many tables, the output will be very big and the internal buffer will be filled. Reissue the command by generating the grants for a smaller set of tables.
If you are not sure about what you are going to execute, issue the previous command without the final part (| db2 +p -tv), this will write the commands in the standard output. However, this part is the most important, because this executes the generated output.
For more details, please check the InfoCenter or my blog http://angocadb2.blogspot.com/2011/12/ejecutar-la-salida-de-un-query-en-clp.html (In Spanish)

oracle has 'DESCRIBE' to get all the details of the table like wise does t/sql has any thing

oracle has 'DESCRIBE' to get all the details of the table like wise does t/sql has any thing.
SQL Server has sp_help/sp_helptext
MySQL has describe
Sql-Server's sp_help is about as close as you get for something built-in. Remeber to put the tablename in as a parameter...:-)
EXEC sp_help 'mytable'
If you're in ssms, you can r-click your query window and opt to output results to text -- it's a little easier to read the output.
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_6tsql/html/913cd5d4-39a3-4a4b-a926-75ed32878884.htm
Also -- you can write your own using the system tables (sys.objects, sys.columns, ...) I think 'DESCRIBE' just gives you column name, nullable, and type... so not nearly as much as sp_help provides.
SELECT * FROM sysobjects WHERE parent_obj = (SELECT id FROM sysobjects WHERE name = 'table_name') AND xtype='PK'
will show table details.
SELECT * FROM sys.Tables
will list all tables
There is no describe equivalent.
you might find this searching for MSSQL instead of T/SQL. Most people talking about Transact SQL are talking about stored procedures.

How to find out the availability of datatype in Postgres

Is there any way to find out particular datatype [say for example chkpass] is available or not through a query ?
PostgreSQL provides a huge amount of meta-data which is easily accessed via SQL. To obtain information about the presence of a (scalar) data type, the information provided by pg_type catalog might be of interest here. Try, for example:
SELECT COUNT(*)
FROM pg_type
WHERE typname = 'chkpass'
run: psql -E
and then, in psql session \dT or \dTS