I am using the following query to grab the index columns on a table along with their data type:
SELECT DISTINCT COL.COLUMN_NAME, COL.DATA_TYPE
FROM DBA_IND_COLUMNS IND
INNER JOIN DBA_TAB_COLUMNS COL
ON ( IND.TABLE_OWNER = COL.OWNER AND IND.TABLE_NAME = COL.TABLE_NAME
AND IND.COLUMN_NAME = COL.COLUMN_NAME)
WHERE IND.TABLE_NAME = 'MY_TABLE' AND TABLE_OWNER = 'SCHEMA'
But how can I grab the columns for just one index, instead of the columns for all the indexes?
For example:
If a table has indexes:
INDEX1: column_a,column_b
INDEX2: column_c,column_d
My current query would result in:
column_a, varchar
column_b, varchar
column_c, varchar
column_d, varchar
but I want it to result in just:
column_a, varchar
column_b, varchar
Since you just want the columns for the first index (in alphabetical order), you can try:
SELECT DISTINCT COL.COLUMN_NAME, COL.DATA_TYPE
FROM DBA_IND_COLUMNS IND
INNER JOIN DBA_TAB_COLUMNS COL
ON ( IND.TABLE_OWNER = COL.OWNER AND IND.TABLE_NAME = COL.TABLE_NAME
AND IND.COLUMN_NAME = COL.COLUMN_NAME)
WHERE IND.TABLE_NAME = 'MY_TABLE' AND TABLE_OWNER = 'SCHEMA'
AND INDEX_NAME =
(
SELECT MIN(INDEX_NAME)
FROM DBA_IND_COLUMNS IIND
INNER JOIN DBA_TAB_COLUMNS CCOL
ON ( IIND.TABLE_OWNER = CCOL.OWNER AND IIND.TABLE_NAME = CCOL.TABLE_NAME )
)
If you need columns in the first index of the table, try filtering with a subquery:
SELECT DISTINCT COL.COLUMN_NAME, COL.DATA_TYPE
FROM DBA_IND_COLUMNS IND
INNER JOIN DBA_TAB_COLUMNS COL
ON ( IND.TABLE_OWNER = COL.OWNER AND IND.TABLE_NAME = COL.TABLE_NAME
AND IND.COLUMN_NAME = COL.COLUMN_NAME)
WHERE IND.TABLE_NAME = 'MY_TABLE' AND TABLE_OWNER = 'SCHEMA'
AND INDEX_NAME = (SELECT MIN(INDEX_NAME)
FROM DBA_IND_COLUMNS IND2
WHERE IND2.TABLE_NAME = IND.TABLE_NAME
AND IND2.TABLE_OWNER = IND.TABLE_OWNER)
This can even be re-written with some analytic function.
Related
I have the following query that I use very frequently to find a table in a database that has a specified column name:
SELECT Table_Name, Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'db' AND COLUMN_NAME = 'col_A'
I'm now trying to find a table that has both of the specified columns in the query (ex: both col_A and col_B). I thought it would have been as simple as just further qualifying the WHERE clause, but that was to no avail. Any tips?
Another way that satisfies the "2 or more" requirement without major modifications:
;WITH input(ColumnName) AS
(
SELECT y FROM (VALUES
/* simply list your columns here: */
(N'col_A'),
(N'col_B')
) AS x(y)
)
SELECT t.name FROM input
INNER JOIN sys.columns AS c ON c.name = input.ColumnName
INNER JOIN sys.tables AS t ON c.[object_id] = t.[object_id]
GROUP BY t.name HAVING COUNT(*) = (SELECT COUNT(*) FROM input);
Example db<>fiddle
And FWIW why I don't use INFORMATION_SCHEMA.
As long as you know the database already, this should work for you:
select t.TABLE_NAME
from INFORMATION_SCHEMA.TABLES t
inner join INFORMATION_SCHEMA.COLUMNS c
on t.TABLE_NAME = c.TABLE_NAME
and c.COLUMN_NAME = 'col_A'
inner join INFORMATION_SCHEMA.COLUMNS c2
on t.TABLE_NAME = c2.TABLE_NAME
and c2.COLUMN_NAME = 'col_B'
If you want all column names and tables names that have both columnname you can do
SELECT Table_Name, Column_Name,TABLE_CATALOG
FROM INFORMATION_SCHEMA.COLUMNS
WHERE EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = 'testdb' AND column_name = 'col_a')
AND EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'testdb' AND column_name = 'col_b')
Aim is to compare tables column_name with the views columns_name to check if they have the same columns , however, getting them with different orders. Wanted to see them both with same order
select t1.COLUMN_NAME, t2.COLUMN_NAME from
(select * from information_schema.columns where TABLE_SCHEMA = 'dmt' and table_name = '#tablename' ) as t1
left join
(select * from information_schema.columns where TABLE_SCHEMA = 'models' and table_name = 'viewName') as t2
on t1.ORDINAL_POSITION = t2.ORDINAL_POSITION
I want get the output like in the same order, for example:
Column_Name 1 Column_Name 2
cat cat
dog dog
You can use the following to get the comparison of the columns.
WITH ColumnsCTE (TABLE_NAME, COLUMN_NAME) AS
(
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dmt' AND TABLE_NAME = 'TableName'
UNION ALL
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'models' AND TABLE_NAME = 'ViewName'
)
-- get the different columns of the tables / views.
SELECT t1.TABLE_NAME, t1.COLUMN_NAME AS [COLUMN_NAME 1], ISNULL(t2.COLUMN_NAME, 'missing on other table / view') AS [COLUMN_NAME 2]
FROM ColumnsCTE AS t1 LEFT JOIN ColumnsCTE AS t2 ON t1.COLUMN_NAME = t2.COLUMN_NAME AND t1.TABLE_NAME <> t2.TABLE_NAME
WHERE t2.COLUMN_NAME IS NULL
demo on dbfiddle.uk
You can't use the ORDINAL_POSITION to get the expected result since the order of the columns can be different. See the following example where the ORDINAL_POSITION is different but the columns are available in both tables / views:
CREATE TABLE Test (
id INT,
name VARCHAR(100)
);
CREATE VIEW ViewTest AS
SELECT name, id FROM Test;
If the order of the attributes is identitcal (you can hardcode which attributes to select and in which order)
i strongly recommend
"intersect" or "except" command
increddibly strong function offering almost anything you could wish for here.
I want to write a SQL statement (SQL Server) which selects column names under specific conditions and "returns" all column names separated by a ,.
SELECT COLUMN_NAME
FROM all_tab_columns
WHERE OWNER = 'KOCH' AND TABLE_NAME = 'TABLE1';
This returns several rows of column names:
NAME
ID
STATE
CITY
But I want them to be returned in this format:
NAME, ID, STATE, CITY
(I think I have to use FROM dual)?
For Oracle:
;WITH CTE_Columns (column_list, column_id) AS
(
SELECT
CAST(COLUMN_NAME AS VARCHAR(500)) AS column_list,
COLUMN_ID
FROM USER_TAB_COLUMNS C
WHERE
TABLE_NAME = 'TABLE1' AND
COLUMN_ID= 1
UNION ALL
SELECT
CAST(column_list + ', ' + C.COLUMN_NAME AS VARCHAR(500)),
C.COLUMN_ID
FROM
CTE_Columns CL
INNER JOIN USER_TAB_COLUMNS C ON
C.TABLE_NAME = 'TABLE1' AND
C.COLUMN_ID = CL.COLUMN_ID + 1
)
SELECT column_list
FROM CTE_Columns
WHERE
COLUMN_ID =
(
SELECT MAX(COLUMN_ID)
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'TABLE1')
I am using the following SQL to grab index columns for a table:
SELECT DISTINCT COLUMN_NAME
FROM DBA_IND_COLUMNS
WHERE TABLE_NAME = 'MY_TABLE' AND TABLE_OWNER = 'SCHEMA'";
I want to adjust this SQL such that I grab the index columns and their data type:
SELECT DISTINCT COLUMN_NAME, DATA_TYPE
FROM DBA_IND_COLUMNS
WHERE TABLE_NAME = 'MY_TABLE' AND TABLE_OWNER = 'SCHEMA'";
But this gives an invalid identifier error for "DATA_TYPE". Is there a way to do this without creating another query?
You need to add DBA_TAB_COLUMNS to your query:
SELECT DISTINCT COL.COLUMN_NAME, COL.DATA_TYPE
FROM DBA_IND_COLUMNS IND
INNER JOIN DBA_TAB_COLUMNS COL
ON ( IND.TABLE_OWNER = COL.OWNER AND IND.TABLE_NAME = COL.TABLE_NAME AND IND.COLUMN_NAME = COL.COLUMN_NAME)
WHERE IND.TABLE_NAME = 'MY_TABLE' AND TABLE_OWNER = 'SCHEMA'
I want to select all the columns from two tables let us say Table A and Table B where A's Column Name is not equal to B's Column Name. I try to find a solution but all i find is how to get common columns.
select A.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS A
join INFORMATION_SCHEMA.COLUMNS B
on A.COLUMN_NAME = B.COLUMN_NAME
where A.TABLE_NAME = 'table1'
and B.TABLE_NAME = 'table2'
I don't want all those columns to be appeared whose name is common, but want all other columns whose name is not same.
;WITH A AS(
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'table1'
),
B AS(
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'table2'
)
SELECT A.COLUMN_NAME FROM A
LEFT OUTER JOIN B
ON A.COLUMN_NAME = B.COLUMN_NAME
WHERE B.COLUMN_NAME IS NULL
UNION ALL
SELECT B.COLUMN_NAME FROM A
RIGHT OUTER JOIN B
ON A.COLUMN_NAME = B.COLUMN_NAME
WHERE A.COLUMN_NAME IS NULL
Use a correlated not exists in the where clause to get columns from Table1 that is not exist in Table2.
select A.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS as A
where A.TABLE_NAME = 'Table1' and
not exists (
select *
from INFORMATION_SCHEMA.COLUMNS as B
where A.COLUMN_NAME = B.COLUMN_NAME and
B.TABLE_NAME = 'Table2'
)
To get the columns from both tables you can use the above query twice and combine the result with a union all.
select A.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS as A
where A.TABLE_NAME = 'Table1' and
not exists (
select *
from INFORMATION_SCHEMA.COLUMNS as B
where A.COLUMN_NAME = B.COLUMN_NAME and
B.TABLE_NAME = 'Table2'
)
union all
select A.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS as A
where A.TABLE_NAME = 'Table2' and
not exists (
select *
from INFORMATION_SCHEMA.COLUMNS as B
where A.COLUMN_NAME = B.COLUMN_NAME and
B.TABLE_NAME = 'Table1'
)
Or you can use except with union all.
select COLUMN_NAME
from (
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'Table1'
except
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS as A
where TABLE_NAME = 'Table2'
) as C
union all
select COLUMN_NAME
from (
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'Table2'
except
select COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS as A
where TABLE_NAME = 'Table1'
) as C