How to get table comments via SQL in Oracle? - sql

I've tried :
select * from user_tab_comments;
and it returns me 3 columns "TABLE_NAME", "TABLE_TYPE", and "COMMENTS", but the "TABLE_NAME" column is like "encrypted", I need clear table names :
TABLE_NAME TABLE_TYPE COMMENTS
BIN$IN1vjtqhTEKcWfn9PshHYg==$0 TABLE Résultat d'intégration d'une photo numérisée
BIN$PUwG3lb3QoazOc4QaC1sjw==$0 TABLE Motif de fin d'agrément de maître de stage
When I use select * from user_tables; TABLE_NAME is not "encrypted".

Since 10g Oracle doesn't immediately drop tables when we issue a DROP TABLE statement. Instead it renames them like this BIN$IN1vjtqhTEKcWfn9PshHYg==$0 and puts them in the recycle bin. This allows us to recover tables we didn't mean to drop. Find out more.
Tables in the recycle bin are still tables, so they show up in ALL_TABLES and similar views. So if you only want to see comments relating only to live (non-dropped) tables you need to filter by table name:
select * from all_tab_comments
where substr(table_name,1,4) != 'BIN$'
/
"I can't believe there isn't a flag column so you could do and is_recycled = 0 or something. "
You're right, it would be incredible. So I checked the documentation it turns out Oracle 10g added a column called DROPPED to the USER_/ALL_/DBA_TABLES views.
select tc.*
from all_tab_comments tc
join all_tables t
on tc.owner = t.owner
and tc.table_name = t.table_name
where t.dropped = 'NO'
/
Check out the documentation. Obviously the need to join to the ALL_TABLES view requires more typing than filtering on the name, so depending on our need it might just be easier to keep the original WHERE clause.

SELECT t.table_name,t.comments FROM USER_TAB_COMMENTS t WHERE TABLE_NAME = 'SS_DEPT';

Related

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;

SQL multiple tables query for column names

I have multiple tables (number > 100) within a database in SQL, each table may have a few hundred entries.
For every table, I am seeking to retrieve simply the names of the columns from the tables which have at least 1 non-null entry.
How can I do this?
To return table/column name:
SELECT table_name, column_name
FROM information_schema.columns
That's pretty easy, here's a solution for nulls depending on if you have permissions:
select a.table_name
, schema_name
, sum(c.rows) total_rows
from
information_schema.tables a
join information_schema.schemas b on (a.schema_id = b.schema_id)
join information_schema.partitions c on (a.object_id = c.object_id)
where c.index_id in (0,1)
group by a.name,b.name
having sum(c.rows) = 0;
Note: I did this in vertica, and you have to have access to partitions. Also, some dbs use sys instead of information_schema, but the idea is the same.

Programmatically get all tables of a database owned by a user

I created the following query:
select
is_tables.table_name
from information_schema.tables is_tables
join pg_tables
on is_tables.table_name=pg_tables.tablename
where
is_tables.table_catalog='<mydatabase>'
and is_tables.table_schema<>'information_schema'
and is_tables.table_schema<>'pg_catalog'
and pg_tables.tableowner='<myuser>';
I assume there is no database vendor independent way of querying this. Is this the easiest/shortest SQL query to achieve what I want in PostgreSQL?
I think you're pretty close. Object owners don't seem to appear in the information_schema views, although I might have overlooked it.
select is_tables.table_schema,
is_tables.table_name
from information_schema.tables is_tables
inner join pg_tables
on is_tables.table_name = pg_tables.tablename
and is_tables.table_schema = pg_tables.schemaname
where is_tables.table_catalog = '<mydatabase>'
and is_tables.table_schema <> 'information_schema'
and is_tables.table_schema <> 'pg_catalog'
and pg_tables.tableowner = '<myuser>';
You need to join on both the table name and the schema name. Table names are unique within a schema; they're not unique within a database.

Oracle 11g : Meta data query very slow

I have this view that should display comments and constraints (including check conditions where applicable) for the columns of some tables in a schema.
Essentially I'm (left ) joining ALL_COL_COMMENTS to ALL_CONS_COLUMNS to ALL_CONSTRAINTS.
However, this is really slow for some reason ( takes around 10 seconds ) even though I have a very small number of tables ( just 7 ) , very small number of columns ( 58 columns in total ). So the query returns few results. And it's still slow. What can I do ?
CREATE OR REPLACE FORCE VIEW "MYDB"."COMMENTS_VIEW" ("TABLE_NAME", "COLUMN_NAME", "COMMENTS", "CONSTRAINT_TYPE", "CHECK_CONDITION") AS
SELECT r.TABLE_NAME, r.COLUMN_NAME, r.COMMENTS, DECODE(q.CONSTRAINT_TYPE,'P', 'Primary Key', 'C', 'Check Constraint', 'R', 'Referential Integrity Constraint' ), q.SEARCH_CONDITION AS CHECK_CONDITION
FROM ALL_COL_COMMENTS r -- ALL_COL_COMMENTS has the COMMENTS
LEFT JOIN ALL_CONS_COLUMNS p ON (p.TABLE_NAME = r.TABLE_NAME AND p.OWNER = 'MYDB' AND p.COLUMN_NAME = r.COLUMN_NAME) -- ALL_CONS_COLUMNS links COLUMNS to CONSTRAINTS
LEFT JOIN ALL_CONSTRAINTS q ON (q.OWNER = 'MYDB' AND q.CONSTRAINT_NAME = p.CONSTRAINT_NAME AND q.TABLE_NAME = p.TABLE_NAME AND (q.CONSTRAINT_TYPE = 'C' OR q.CONSTRAINT_TYPE = 'P' OR q.CONSTRAINT_TYPE = 'R' ) ) -- this gives us INFO on CONSTRAINTS
WHERE r.OWNER = 'MYDB'
AND
r.TABLE_NAME IN ('TABLE1', 'TABLE2', 'TABLE3', 'TABLE4', 'TABLE5', 'TABLE6', 'TABLE7')
AND
r.COLUMN_NAME NOT IN ('CREATED', 'MODIFIED', 'CREATED_BY', 'MODIFIED_BY')
ORDER BY r.TABLE_NAME, r.COLUMN_NAME, r.COMMENTS;
Ensure the dictionary and fixed object statistics are up-to-date. Checking for up-to-date statistics is a good first step for almost any SQL performance problem. The dictionary and fixed objects are unusual, and there's a good chance nobody has considered gathering statistics on them before.
begin
dbms_stats.gather_fixed_objects_stats;
dbms_stats.gather_dictionary_stats;
end;
/
Try to join on table, and column ids instead of names where possible. Even OWNER if you can. Example:
ON p.TABLE_ID = r.TABLE_ID
Also, you are selecting from objects that are already views of who knows how many underlying tables. The query optimizer is probably having a hard time (and maybe giving up in some aspects). Try to translate your query into using the base tables.
I would either use a query profiler, or (simpler) just remove parts of your query until it gets super fast. For example, remove the DECODE() call, maybe that's doing it.

Dynamically determining table name given field name in SQL server

Strange situation: I am trying to remove some hard coding from my code. There is a situation where I have a field, lets say "CityID", and using this information, I want to find out which table contains a primary key called CityID.
Logically, you'd say that it's probably a table called "City" but it's not... that table is called "Cities". There are some other inconsistencies in database naming hence I can never be sure if removing the string "ID" and finding out the plural will be sufficient.
Note: Once I figure out that CityID refers to a table called Cities, I will perform a join to replace CityID with city name on the fly. I will appreciate if someonw can also tell me how to find out the first varchar field in a table given its name.
SELECT name FROM sysobjects
WHERE id IN ( SELECT id FROM syscolumns WHERE name = 'THE_COLUMN_NAME' )
To get column information from the specified table:
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'myTable'
select table_name from information_schema.columns where column_name='CityID'
You can use the INFORMATION_SCHEMA tables to read metadata about the database.
SELECT
TABLE_NAME
FROM
[db].[INFORMATION_SCHEMA].[COLUMNS]
WHERE
COLUMN_NAME='CityID';
For a primer in what's in the INFORMAITON_SCHEMA, see INFORMATION_SCHEMA, a map to your database
The information you seek is all available in the information schema views. Note that you will find many sources telling you how to directly query the underlying system tables that these are views onto - and I must admit that I do the same when it's just to find something out quickly - but the recommended way for applications is to go through these views.
For example, to find your CityID column:
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'CityID'
To find the first varchar field in a table:
SELECT TOP 1 * FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME = 'TableName'
AND DATA_TYPE = 'varchar' -- This is off the top of my head!
ORDER BY ORDINAL_POSITION
As I understand from your question, you want to find tables which contain CITYID column in primary key
You can use SQL Server system views like sysindexes and sysindexkeys as shown in SQL tutorial to query database table primary keys including composite primary keys which are formed
SELECT
TBL.name as TableName
FROM sysobjects as PK
INNER JOIN sys.objects as TBL
on TBL.object_id = PK.parent_obj
INNER JOIN sysindexes as IND
on IND.name = PK.name AND
IND.id = TBL.object_id
INNER JOIN SysIndexKeys as KEYS
on KEYS.id = IND.id AND
KEYS.indid = IND.indid
INNER JOIN syscolumns as COL
on COL.id = KEYS.id AND
COL.colid = KEYS.colid
WHERE
PK.xtype = 'PK' AND
COL.name = 'CityID'