What table a column is keyed to - sql-server

I have a query that gives me my column names, data type, max length, nullable...
I also need to know the name of the table the column refers to if it has a foreign key.
Here is my query
SELECT
c.name 'Column Name',
t.Name 'Data type',
c.max_length 'Max Length',
c.is_nullable,
ISNULL(i.is_primary_key, 0) 'Primary Key'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.system_type_id = t.system_type_id
LEFT OUTER JOIN
sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
WHERE
c.object_id = OBJECT_ID('Table_Name')

Thanks to Devart, you got me on the right path.
Here is the answer for future reference
SELECT
[Column Name] = c.name
, [Data type] = t.name
, [Max Length] = c.max_length
, c.is_nullable
, [Primary Key] = ISNULL(i.is_primary_key, 0)
, OBJECT_NAME(fkc.referenced_object_id)
FROM sys.columns c WITH(NOWAIT)
JOIN sys.types t WITH(NOWAIT) ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id
LEFT JOIN (
SELECT i.[object_id], ic.column_id, i.is_primary_key
FROM sys.indexes i WITH(NOWAIT)
JOIN sys.index_columns ic WITH(NOWAIT) ON ic.[object_id] = i.[object_id]
AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
) i ON c.[object_id] = i.[object_id] AND c.column_id = i.column_id
LEFT JOIN sys.foreign_key_columns fkc WITH(NOWAIT) ON fkc.parent_object_id = c.[object_id]
AND fkc.parent_column_id = c.column_id
WHERE c.[object_id] = OBJECT_ID('TableName')

Try this one -
SELECT
[Column Name] = c.name
, [Data type] = t.name
, [Max Length] = c.max_length
, c.is_nullable
, [Primary Key] = ISNULL(i.is_primary_key, 0)
, IsFK = ISNULL(fkc.parent_object_id / fkc.parent_object_id, 0)
FROM sys.columns c WITH(NOWAIT)
JOIN sys.types t WITH(NOWAIT) ON c.system_type_id = t.system_type_id AND c.user_type_id = t.user_type_id
LEFT JOIN (
SELECT i.[object_id], ic.column_id, i.is_primary_key
FROM sys.indexes i WITH(NOWAIT)
JOIN sys.index_columns ic WITH(NOWAIT) ON ic.[object_id] = i.[object_id]
AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
) i ON c.[object_id] = i.[object_id] AND c.column_id = i.column_id
LEFT JOIN sys.foreign_key_columns fkc WITH(NOWAIT) ON fkc.parent_object_id = c.[object_id]
AND fkc.parent_column_id = c.column_id
WHERE c.[object_id] = OBJECT_ID('Table_Name')

Related

Bypassing LCK_M_SCH_S lock when requesting partition information

I have code to query partition data.
But when the database creates an index, my query does not work because of the LCK_M_SCH_S lock, although I use the NOLOCK hint for all tables.
Is there any way around this lock?
SELECT DB_NAME() AS DatabaseName
, OBJECT_SCHEMA_NAME(p.OBJECT_ID) as TableschemaName
, OBJECT_NAME(p.OBJECT_ID) AS TableName
, p.index_id AS 'IndexId'
, CASE WHEN p.index_id = 0 THEN 'HEAP'
ELSE i.name
END AS 'IndexName'
, p.partition_number AS PartitionNumber
, prv_left.value AS LowerBoundary
, prv_right.value AS UpperBoundary
, ps.name as PartitionScheme
, pf.name as PartitionFunction
, c.name AS [Partitioning Column]
, TYPE_NAME(c.user_type_id) AS [Column Type]
, CASE WHEN fg.name IS NULL THEN ds.name
ELSE fg.name
END AS 'FileGroupName'
, CAST(p.used_page_count * 0.0078125 AS NUMERIC(18,2)) AS UsedPagesMB
, CAST(p.in_row_data_page_count * 0.0078125 AS NUMERIC(18,2)) AS DataPagesMB
, CAST(p.reserved_page_count * 0.0078125 AS NUMERIC(18,2)) AS ReservedPagesMB
, CASE WHEN p.index_id IN (0,1) THEN p.row_count
ELSE 0
END AS RowsQuantity
,CASE WHEN p.index_id IN (0,1) THEN 'data'
ELSE 'index'
END AS Type
FROM sys.dm_db_partition_stats p WITH (NOLOCK)
JOIN sys.indexes i WITH (NOLOCK) ON i.OBJECT_ID = p.OBJECT_ID AND i.index_id = p.index_id
JOIN sys.data_spaces ds WITH (NOLOCK) ON ds.data_space_id = i.data_space_id
LEFT JOIN sys.partition_schemes ps WITH (NOLOCK) ON ps.data_space_id = i.data_space_id
LEFT JOIN sys.partition_functions pf WITH (NOLOCK) ON ps.function_id = pf.function_id
LEFT JOIN sys.destination_data_spaces dds WITH (NOLOCK) ON dds.partition_scheme_id = ps.data_space_id
AND dds.destination_id = p.partition_number
LEFT JOIN sys.filegroups fg WITH (NOLOCK) ON fg.data_space_id = dds.data_space_id
LEFT JOIN sys.partition_range_values prv_right WITH (NOLOCK) ON prv_right.function_id = ps.function_id
AND prv_right.boundary_id = p.partition_number
LEFT JOIN sys.partition_range_values prv_left WITH (NOLOCK) ON prv_left.function_id = ps.function_id
AND prv_left.boundary_id = p.partition_number - 1
LEFT JOIN sys.index_columns ic WITH (NOLOCK) ON ic.[object_id] = i.[object_id]
AND ic.index_id = i.index_id
AND ic.partition_ordinal >= 1
LEFT JOIN sys.columns c WITH (NOLOCK) ON p.OBJECT_ID = c.[object_id]
AND ic.column_id = c.column_id
WHERE OBJECTPROPERTY(p.OBJECT_ID, 'ISMSSHipped') = 0
AND p.index_id IN (0,1)
AND ps.name IS NOT NULL

Optimize long query to find database schema with foreign keys and tables

I am writing a query to get all the tables in the db with their properties but also foreign keys and table that each reference to. I have a following query but it is taking 60 min to complete. Not sure what am I doing wrong?
SELECT
ist.table_name,
isc.column_name,
data_type,
character_maximum_length,
Columnproperty(Object_id(isc.table_name),
isc.column_name, 'IsIdentity') AS identityFlag,
is_nullable,
character_maximum_length,
numeric_scale,
(SELECT 1
FROM information_schema.table_constraints AS C
JOIN information_schema.key_column_usage AS K ON C.table_name = K.table_name
AND C.constraint_catalog = K.constraint_catalog
AND C.constraint_schema = K.constraint_schema
AND C.constraint_name = K.constraint_name
WHERE C.constraint_type = 'PRIMARY KEY'
AND C.table_name = isc.table_name
AND K.column_name = isc.column_name) AS primarykey,
(SELECT TOP 1 1
FROM information_schema.table_constraints AS C
JOIN information_schema.key_column_usage AS K ON C.table_name = K.table_name
AND C.constraint_catalog = K.constraint_catalog
AND C.constraint_schema = K.constraint_schema
AND C.constraint_name = K.constraint_name
WHERE C.constraint_type = 'FOREIGN KEY'
AND C.table_name = isc.table_name
AND K.column_name = isc.column_name) AS foreignKey,
a.parenttablename AS foreignTableName,
a.colname AS foreignColumnName
FROM
information_schema.tables ist
INNER JOIN
information_schema.columns isc ON ist.table_name = isc.table_name
LEFT OUTER JOIN
(SELECT
t.NAME AS parentTableName,
Object_name(f.parent_object_id) TableName,
Col_name(fc.parent_object_id, fc.parent_column_id) ColName
FROM
sys.foreign_keys AS f
INNER JOIN
sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
INNER JOIN
sys.tables t ON t.object_id = fc.referenced_object_id) a ON a.tablename = ist.table_name
AND a.colname = isc.column_name
It is taking time to find the foreign table names. What is the best way to get db table schema
Firstly, you should stick to the sys schema, as these catalog views are more efficient, and INFORMATION_SCHEMA is only for compatibility
You are over-complicating it. You don't need to query the foreign key twice, you can just check if the LEFT JOIN succeeded by checking for NULL
SELECT
t.name AS table_name,
c.name AS column_name,
typ.name AS data_type,
c.max_length,
c.is_identity AS identityFlag,
c.is_nullable,
c.precision,
c.scale,
CASE WHEN EXISTS (SELECT 1
FROM sys.indexes AS i
JOIN sys.index_columns AS ic
ON ic.object_id = i.object_id
AND ic.index_id = i.index_id
WHERE i.object_id = t.object_id
AND ic.column_id = c.column_id
) THEN 1 ELSE 0 END AS primarykey,
CASE WHEN t_f.name IS NOT NULL THEN 1 ELSE 0 END AS foreignKey,
t_f.name AS foreignTableName,
c_f.name AS foreignColumnName
FROM
sys.tables t
INNER JOIN
sys.columns c ON c.object_id = t.object_id
INNER JOIN
sys.types typ ON typ.user_type_id = c.user_type_id
LEFT OUTER JOIN
sys.foreign_key_columns AS fc
INNER JOIN
sys.tables t_f ON t_f.object_id = fc.referenced_object_id
INNER JOIN
sys.columns c_f ON c_f.object_id = t_f.object_id
AND c_f.column_id = fc.referenced_column_id
ON fc.parent_object_id = t.object_id
AND fc.parent_column_id = c.column_id;

Test existing column in query in SQL Server

I have this script below:
---------Part 1--------
SELECT
COLUMN_NAME
FROM
(SELECT
SC.name as TABLE_SCHEMA,
t.name as TABLE_NAME,
ind.name as indexName,
ind.type_desc AS type_Index,
SUBSTRING((SELECT ', ' + AC.name
FROM DATA.sys.[tables] AS T
INNER JOIN DATA.sys.[indexes] I ON T.[object_id] = I.[object_id]
INNER JOIN DATA.sys.[index_columns] IC ON I.[object_id] = IC.[object_id] AND I.[index_id] = IC.[index_id]
INNER JOIN DATA.sys.[all_columns] AC ON T.[object_id] = AC.[object_id] AND IC.[column_id] = AC.[column_id]
WHERE Ind.[object_id] = I.[object_id] AND Ind.index_id = I.index_id AND IC.is_included_column = 0
ORDER BY IC.key_ordinal
FOR XML PATH('')), 2, 8000) AS COLUMN_NAME
FROM DATA.sys.indexes ind
INNER JOIN DATA.sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
INNER JOIN DATA.sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN DATA.sys.tables t ON ind.object_id = t.object_id
INNER JOIN DATA.sys.schemas SC ON t.schema_id = SC.schema_id
WHERE SC.name ='SCHEMA1') AS SubQ
WHERE
COLUMN_NAME IN
-------Part 2-------
(SELECT COLUMN_NAME
FROM DATA.INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE IN ('nchar', 'nvarchar')
AND TABLE_SCHEMA IN ('SCHEMA1', 'SCHEMA2'))
When I run the part 1 or the part 2, I got the best the columns, and the two results are the same, but when I run all the script it does not dispaly any thing, and no errors.
Some help please ?
Thank you

get column names of table vs determine column is primary key or not (sql)

i want to get all columns of table vs an extra column that determine field is Primary Key or not.i'm using this code:
SELECT c.column_id ID, c.name ItemName,
CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END ISPK
FROM sys.tables tb
JOIN sys.columns c
ON tb.name = 'register'
AND tb.[object_id] = c.[object_id]
JOIN sys.types tp
ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc
ON c.[object_id] = cc.[object_id]
AND c.column_id = cc.column_id
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K
ON c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon
ON tblCon.TABLE_NAME = 'register'
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
in this example tablename is "register".
this code is correct but for primary key field return two records:1
What's the problem?
Added one more required column as details.
SELECT c.column_id ID, c.name ItemName,
CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END ISPK,
ISNULL(tblCon.CONSTRAINT_TYPE,'') as Detail
FROM sys.tables tb
JOIN sys.columns c
ON tb.name = 'register'
AND tb.[object_id] = c.[object_id]
JOIN sys.types tp
ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc
ON c.[object_id] = cc.[object_id]
AND c.column_id = cc.column_id
LEFT JOIN (select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where (CONSTRAINT_NAME like 'PK_%' or CONSTRAINT_NAME like 'FK_%') and TABLE_NAME='register') AS K
ON c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon
ON tblCon.TABLE_NAME = 'register'
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
This should work
SELECT c.column_id ID, c.name ItemName,
CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END ISPK
FROM sys.tables tb
JOIN sys.columns c
ON tb.name = 'register'
AND tb.[object_id] = c.[object_id]
JOIN sys.types tp
ON c.user_type_id = tp.user_type_id
LEFT JOIN sys.computed_columns cc
ON c.[object_id] = cc.[object_id]
AND c.column_id = cc.column_id
LEFT JOIN (select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where CONSTRAINT_NAME like 'PK_%' and TABLE_NAME='register') AS K
ON c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon
ON tblCon.TABLE_NAME = 'register'
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
Taking the answer from Sagar and cleaning it up considerably. There were two extra joins, I change the subquery to a left join and modified some of the join conditions so the table name only need to be entered once.
SELECT c.column_id AS ID
, c.name AS ItemName
, CASE
WHEN tblCon.CONSTRAINT_TYPE = 'PRIMARY KEY' THEN 1
ELSE 0
END AS ISPK
FROM sys.tables tb
JOIN sys.columns c ON
tb.object_id = c.object_id
AND tb.[object_id] = c.[object_id]
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE K on
CONSTRAINT_NAME like 'PK_%'
and TABLE_NAME = tb.name
AND c.name = k.COLUMN_NAME
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tblCon ON
tblCon.TABLE_NAME = tb.name
AND tblCon.CONSTRAINT_CATALOG = K.CONSTRAINT_CATALOG
AND tblCon.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA
AND tblCon.CONSTRAINT_NAME = K.CONSTRAINT_NAME
where tb.name = 'register'

List which columns have a full-text index in SQL Server 2005

How do I list all tables / columns in my database that have a full-text index?
select distinct
object_name(fic.[object_id]) table_name,
[name] column_name
from
sys.fulltext_index_columns fic
inner join sys.columns c
on c.[object_id] = fic.[object_id]
and c.[column_id] = fic.[column_id]
This one gives you more information
SELECT
t.name AS TableName,
c.name AS FTCatalogName ,
i.name AS UniqueIdxName,
cl.name AS ColumnName,
cdt.name AS DataTypeColumnName
FROM
sys.tables t
INNER JOIN
sys.fulltext_indexes fi
ON
t.[object_id] = fi.[object_id]
INNER JOIN
sys.fulltext_index_columns ic
ON
ic.[object_id] = t.[object_id]
INNER JOIN
sys.columns cl
ON
ic.column_id = cl.column_id
AND ic.[object_id] = cl.[object_id]
INNER JOIN
sys.fulltext_catalogs c
ON
fi.fulltext_catalog_id = c.fulltext_catalog_id
INNER JOIN
sys.indexes i
ON
fi.unique_index_id = i.index_id
AND fi.[object_id] = i.[object_id]
LEFT JOIN
sys.columns cdt
ON
ic.type_column_id = cdt.column_id
AND fi.object_id = cdt.object_id;

Resources