I am trying to retrieve the primary keys for a table name EMPLOYEE as follows
SELECT cols.column_name
FROM all_constraints cons, all_cons_columns cols
WHERE cols.table_name ='EMPLOYEE'
AND cons.constraint_type = 'P'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
ORDER BY cols.table_name, cols.position
The table EMPLOYEE exists for another user which also has a primary key called ID
So the result of the above query gives (ID, ID) instead of (ID) from the current user. How do I get only the primary keys of the tables belonging to the user's schema
Switch to USER_* views instead of ALL_*.
Eliminate conditions on the OWNER columns in your query.
ALL_* views return everything the querying schema has access to including the objects the schema owns, in contrast to
USER_* views returning only the objects the schema is owner of
DBA_* views return all objects in database
Therefore, you can query USER_* views or you can query DBA_* views specifying the condition on the OWNER column.
In your case your query could look like this.
select
cons.table_name
, cons.constraint_name
, cols.column_name
, cols.position
from user_constraints cons, user_cons_columns cols
where cons.constraint_name = cols.constraint_name
and constraint_type = 'P'
order by cons.table_name;
For more details about data dictionary and views' and their scope, consult the Data Dictionary and Dynamic Performance Views section in Concepts.
Related
I've got this SQL Query that I need to write for Oracle, please could you help ?
SELECT key_column_usage.column_name
FROM information_schema.key_column_usage
WHERE table_schema = SCHEMA()
AND constraint_name = 'PRIMARY'
AND table_name = 'posts'
I don't know what parts of your query represent, but - let me try. It looks like you'd like to query constraints table. If so, then one option is to query user_cons_columns:
from user_cons_columns c
where c.owner = user
and c.constraint_name = 'PRIMARY'
and c.table_name = 'POSTS'
where
user represents currently logged user
'PRIMARY' is name of that constraint
'POSTS' is table name; in Oracle, by default, table names are stored in UPPERCASE
Alternatively, join user_constraints and user_cons_columns:
from user_constraints r join user_cons_columns c on c.constraint_name = r.constraint_name
where r.owner = 'SCOTT'
and r.constraint_type = 'P'
and r.table_name = 'POSTS'
because constraint_type = 'P' represents primary keys (if that's what you actually want), and it is stored in user_constraints.
Just for example, this time I used 'SCOTT' as an owner name.
If you want and/or have sufficient privileges, instead of user_, you can query all_ or dba_ views to fetch information you need. So, that would be e.g. all_cons_columns etc.
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.
How can I get column name, data type, size and comments of table?
I tried
SELECT all_tab.column_name, all_tab.data_type, all_tab.data_length, col_com.COMMENTS
FROM all_tab_columns all_tab
JOIN user_col_comments col_com ON all_tab.TABLE_NAME = col_com.TABLE_NAME
WHERE all_tab.TABLE_NAME='MY_TABLE'
But it didn't work.
You need to add column name connection:
SELECT all_tab.column_name,
all_tab.data_type,
all_tab.data_length,
(SELECT COMMENTS
FROM user_col_comments t
where t.TABLE_NAME = all_tab.TABLE_NAME
and t.COLUMN_NAME = all_tab.column_name)
FROM all_tab_columns all_tab
WHERE all_tab.TABLE_NAME = 'MY_TABLE'
The USER_ views show information about objects, tables in this case, that are owned by the schema user you are connecting as. The ALL_ views show information abut objects that the connected schema user has permissions to see.
If you are only interested in objects that are created by the schema owner then by all means use the USER_ views.
However, you probably want;
SELECT all_tab.owner,
all_tab.table_name,
all_tab.column_name,
all_tab.data_type,
all_tab.data_length,
col_com.comments
FROM all_tab_columns all_tab
JOIN all_col_comments col_com
ON all_tab.table_name = col_com.table_name
AND all_tab.owner = col_com.owner
WHERE all_tab.table_name = 'MY_TABLE'
This certainly works for me but you might want to consider also retrieving the DATA_PRECISION and DATA_SCALE
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.
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'