Search an Oracle database for tables with specific column names? - sql

We have a large Oracle database with many tables. Is there a way I can query or search to find if there are any tables with certain column names?
IE show me all tables that have the columns: id, fname, lname, address
Detail I forgot to add: I need to be able to search through different schemas. The one I must use to connect doesn't own the tables I need to search through.

To find all tables with a particular column:
select owner, table_name from all_tab_columns where column_name = 'ID';
To find tables that have any or all of the 4 columns:
select owner, table_name, column_name
from all_tab_columns
where column_name in ('ID', 'FNAME', 'LNAME', 'ADDRESS');
To find tables that have all 4 columns (with none missing):
select owner, table_name
from all_tab_columns
where column_name in ('ID', 'FNAME', 'LNAME', 'ADDRESS')
group by owner, table_name
having count(*) = 4;

TO search a column name use the below query if you know the column name accurately:
select owner,table_name from all_tab_columns where upper(column_name) =upper('keyword');
TO search a column name if you dont know the accurate column use below:
select owner,table_name from all_tab_columns where upper(column_name) like upper('%keyword%');

The data you want is in the "cols" meta-data table:
SELECT * FROM COLS WHERE COLUMN_NAME = 'id'
This one will give you a list of tables that have all of the columns you want:
select distinct
C1.TABLE_NAME
from
cols c1
inner join
cols c2
on C1.TABLE_NAME = C2.TABLE_NAME
inner join
cols c3
on C2.TABLE_NAME = C3.TABLE_NAME
inner join
cols c4
on C3.TABLE_NAME = C4.TABLE_NAME
inner join
tab t
on T.TNAME = C1.TABLE_NAME
where T.TABTYPE = 'TABLE' --could be 'VIEW' if you wanted
and upper(C1.COLUMN_NAME) like upper('%id%')
and upper(C2.COLUMN_NAME) like upper('%fname%')
and upper(C3.COLUMN_NAME) like upper('%lname%')
and upper(C4.COLUMN_NAME) like upper('%address%')
To do this in a different schema, just specify the schema in front of the table, as in
SELECT * FROM SCHEMA1.COLS WHERE COLUMN_NAME LIKE '%ID%';
If you want to combine the searches of many schemas into one output result, then you could do this:
SELECT DISTINCT
'SCHEMA1' AS SCHEMA_NAME
,TABLE_NAME
FROM SCHEMA1.COLS
WHERE COLUMN_NAME LIKE '%ID%'
UNION
SELECT DISTINCT
'SCHEMA2' AS SCHEMA_NAME
,TABLE_NAME
FROM SCHEMA2.COLS
WHERE COLUMN_NAME LIKE '%ID%'

Here is one that we have saved off to findcol.sql so we can run it easily from within SQLPlus
set verify off
clear break
accept colnam prompt 'Enter Column Name (or part of): '
set wrap off
select distinct table_name,
column_name,
data_type || ' (' ||
decode(data_type,'LONG',null,'LONG RAW',null,
'BLOB',null,'CLOB',null,'NUMBER',
decode(data_precision,null,to_char(data_length),
data_precision||','||data_scale
), data_length
) || ')' data_type
from all_tab_columns
where column_name like ('%' || upper('&colnam') || '%');
set verify on

Related

Is there a function to return which phrase in array the row matched when using LIKE ANY (array['%term1%', '%term2%', etc.])?

I want all tables from my schema that match a list of other tables with similar names from a different schema. I am using the following query:
SELECT TABLE_NAME, COUNT(COLUMN_NAME) ColCount
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'schema_2' and TABLE_NAME LIKE ANY (array[
'%table1%',
'%table2%',
'%table3%',
'%table4%',
'%table5%'])
I want another column added to the output which specifies which name in the array the table from schema_2 matched, i.e.
TABLE_NAME COL_COUNT SCHEMA_1_TABLE
table1a 15 table1
Is there a way to do this?
You could try using a join. Kind of like:
WITH a AS (SELECT unnest(array['%table1%','%table2%','%table3%','%table4%','%table5%'])
AS table)
SELECT
isc.TABLE_NAME,
COUNT(isc.COLUMN_NAME),
REPLACE(a.table,'%','')
FROM
INFORMATION_SCHEMA.COLUMNS isc
LEFT JOIN a ON (isc.TABLE_NAME LIKE a.table)
WHERE
isc.TABLE_SCHEMA = 'schema_2'
AND a.table IS NOT NULL
GROUP BY
isc.TABLE_NAME,
a.table
You could also join INFORMATION_SCHEMA.COLUMNS with INFORMATION_SCHEMA.TABLES in order to just detect any duplication, not just the ones specified.

Searching for list of tables from tab when only partial names of the tables are present

I want to get the list of tables from tab , but I only have partial names of the tables :-
For example:-
SELECT COLUMN_NAME1 FROM TABlE_NAME ;
This returns a list of data : A,B,C,D
The aforementioned data is actually part of a table's name like tableprefix_A_tablesuffix.
I want the list of these tables from TAB or user_tables using partial name available.
This should be ok:
SELECT COLUMN_NAME1 PATTERN, U.TABLE_NAME
FROM TABLE_NAME T, USER_TABLES U
WHERE REGEXP_INSTR(U.TABLE_NAME, '(^|_)' || T.COLUMN_NAME1 || '($|_)') != 0
It retrieves patterns like A_%, %_A_%, %_A.
How about joining the two with the like operator:
SELECT u.table_name
FROM user_tables
JOIN table_name t ON u.table_name like '%' || t.column_name1 || '%'

Find all tables without a certain column name

So, I've seen lots of questions about finding all tables with a specific column name. However, I'm trying to find all tables WITHOUT a specific column. (In this case, EndDate). Is there a more elegant solution than just finding all the tables with that column, and comparing it to the list of all tables?
SELECT
table_name
FROM
INFORMATION_SCHEMA.TABLES T
WHERE
T.TABLE_CATALOG = 'MyDB' AND
T.TABLE_TYPE = 'BASE TABLE' AND
NOT EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE
C.TABLE_CATALOG = T.TABLE_CATALOG AND
C.TABLE_SCHEMA = T.TABLE_SCHEMA AND
C.TABLE_NAME = T.TABLE_NAME AND
C.COLUMN_NAME = 'EndDate')
Try the following, It's standard SQL (and will work for almost every platform)
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
EXCEPT
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'EndDate'
Just as you suggested, you can't really get anything that's simpler than this.
This should do it.
SELECT * FROM INFORMATION_SCHEMA.TABLES t
WHERE NOT EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = t.TABLE_NAME AND c.TABLE_SCHEMA=t.TABLE_SCHEMA
AND c.COLUMN_NAME='EndDate')
I have many more schemas and tables than I really ought to, so I need an optimized version that runs in a second.
Why not get all tables, then get all tables with the field, UNION ALL these results, and just show the table names where HAVING COUNT(table_name) = 1? That's just what I did.
Notice the two vars to change below: YourSchemaHere and YourFieldHere.
SELECT TABLE_NAME, COUNT(TABLE_NAME) FROM (
(SELECT DISTINCT c1.TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS c1
WHERE c1.Table_Schema = "YourSchemaHere")
UNION ALL
(SELECT DISTINCT c2.TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS c2
WHERE c2.Table_Schema = "YourSchemaHere" AND
c2.Column_Name = "YourFieldHere")
) x GROUP BY TABLE_NAME
HAVING COUNT(TABLE_NAME) = 1;
Online Demo at SQL Fiddle: http://sqlfiddle.com/#!9/791dde/1/0
Explanation of my approach:
Get all tables with : SELECT DISTINCT c1.TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS c1 WHERE c1.Table_Schema = "YourSchemaHere"
Get all tables with column : SELECT DISTINCT c2.TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS c2 WHERE c2.Table_Schema = "YourSchemaHere" AND c2.Column_Name = "YourFieldHere"
UNION ALL these two results.
Items in resulting list will be duplicated if they have the column, but only appear once if they do not.
Select only those without the field:HAVING COUNT(*) = 1

mysql get table column names in alphabetical order

Is it possible to query a MySQL database to get the column names of a table in alphabetical order? I know that
SHOW COLUMNS `table_name`;
or
DESCRIBE `table_name`;
will give me a list of the columns in a table (along with other info), but is it possible to alter the query in order to get the columns sorted alphabetically. Adding ORDER BY 'Field' didn't work, it gave a syntax error.
The ANSI INFORMATION_SCHEMA tables (in this case, INFORMATION_SCHEMA.COLUMNS) provide more flexibility in MySQL:
SELECT c.column_name
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.table_name = 'tbl_name'
-- AND c.table_schema = 'db_name'
ORDER BY c.column_name
Every field was listed twice until I used group by column name
select c.COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS c
where c.TABLE_NAME = `'tbl_name'`
group by c.column_name
order by c.column_name
If you want more details, below query is really handy:
SELECT COLUMN_NAME as 'Field',
COLUMN_TYPE as 'Type',
IS_NULLABLE as 'Null',
COLUMN_KEY as 'Key',
COLUMN_DEFAULT as 'Default',
EXTRA as 'Extra'
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'my table' and
TABLE_SCHEMA = 'my database'
add ordering
order by Type; --

Find all tables with a field containing xml string values

I have an SQL 2005 database and I know that in the database there is a table which has got some xml strings in it. How can I find this table(s)?
If the fields are actually of type XML, then this query will give you what you're looking for:
select * from information_schema.columns
where DATA_TYPE = 'XML'
Marc
Run this:
select 'select distinct ''' || a.name || '.' || b.name
|| ''' from ' || b.name
|| 'where ' || b.name || ' like ''%<%/>%'' union '
from systable a
join syscolumns b on (a.id = b.id)
join systypes c on (b.type = c.xtype)
where a.type ='U' and c.name = ('CHAR', 'CHARN', 'VARCHAR', 'VARCHARN');
The first result set will have one row per character column in the database:
select distinct 'table.column' from table where column like '%<%/>%' union
Take that resultset, snip off the last union, and run the resultset as a SQL statement. It'll bring back the table name and column name for any column that has one or more rows that look XML-ish.
Edit: this is from memory; the join to systypes and the type names may be wrong, so select from systypes and check.