Get the unique constraint columns list (in TSQL)?

Sql ServerTsqlMetadataConstraints

Sql Server Problem Overview


I can get a list of unique constraints fairly easily with the following query:

select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE='UNIQUE'

But how do I get a list of the columns that each unique constraint applies to?

Sql Server Solutions


Solution 1 - Sql Server

Ed is correct, the columns are exposed on the constraint column usage view, here is the SQL for it.

select TC.Constraint_Name, CC.Column_Name from information_schema.table_constraints TC
inner join information_schema.constraint_column_usage CC on TC.Constraint_Name = CC.Constraint_Name
where TC.constraint_type = 'Unique'
order by TC.Constraint_Name

Solution 2 - Sql Server

See INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE

Solution 3 - Sql Server

SELECT *
FROM    sys.indexes i
        JOIN sys.index_columns ic
            ON i.index_id = ic.index_id
               AND i.object_id = ic.object_id
WHERE i.is_unique_constraint = 1;

Solution 4 - Sql Server

Just for reference of mySQL users, Same thing can be achieved with below queries:

To find any unique constraint on a table

select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where CONSTRAINT_TYPE='UNIQUE' and table_name='db_my_table'

To find unique column list with all column

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where CONSTRAINT_NAME='cons_name' and TABLE_NAME='db_my_table'

to find unique column list with required view

select CONSTRAINT_NAME,COLUMN_NAME,TABLE_NAME from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where CONSTRAINT_NAME='cons_name' and TABLE_NAME='db_my_table'

Solution 5 - Sql Server

Necromancing.
INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE is incredibly slow.

Use sys.indexes, join the table, schema, object, and as an added bonus, you get not only unique constraints, but also unique indices, including filter.

-- CREATE TABLE dbo.T_User( USR_ID int NOT NULL, USR_User nvarchar(256) NULL, USR_Status int NOT NULL );
-- ALTER TABLE dbo.T_User ADD CONSTRAINT UC_T_User_USR_User UNIQUE(USR_User)

-- IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'dbo.T_User') AND name = N'IX_T_User_USR_User')
-- CREATE UNIQUE INDEX IX_T_User_USR_User ON dbo.T_User(USR_User)
-- WHERE (USR_User IS NOT NULL AND USR_Status=(1))

SELECT 
	 sch.name 
	,st.name 
	,i.name 
	,i.has_filter 
	,i.filter_definition 
	,i.is_unique 
	,i.is_primary_key 
	,i.is_unique_constraint 
	 
	,CASE WHEN i.is_unique_constraint = 1 
		THEN N'ALTER TABLE ' + QUOTENAME(sch.name) + N'.' + QUOTENAME(st.name) + N' DROP CONSTRAINT ' + QUOTENAME(i.name) + N'; ' 
		ELSE N'DROP INDEX ' + QUOTENAME(i.name)  + N' ON ' + QUOTENAME(sch.name)  + '.' + QUOTENAME(st.name) + '; ' 
	END AS sql 
FROM sys.indexes AS i

INNER JOIN sys.index_columns AS ic 
	ON i.index_id = ic.index_id 
	AND i.object_id = ic.object_id 

INNER JOIN sys.tables AS st 
	ON st.object_id = i.object_id 

INNER JOIN sys.objects AS syso 
	ON syso.object_id = st.object_id 
	AND syso.is_ms_shipped = 0 

INNER JOIN sys.schemas AS sch 
	ON sch.schema_id = st.schema_id 
	
WHERE (1=1) 
AND NOT EXISTS  
(
	SELECT * 
	FROM sys.extended_properties AS xp 
	WHERE xp.minor_id = 0 
	AND xp.major_id = st.object_id 
	AND xp.name = 'microsoft_database_tools_support' 
)

-- AND sch.name = 'dbo' 
-- AND st.name = 'T_Benutzer'

AND 
(
	i.is_unique_constraint = 1 
	OR 
	(i.is_unique = 1 AND i.is_primary_key = 0)
)
;

Solution 6 - Sql Server

Here is a better solution, which lists the constraint columns in a proper sort order, with added ASC/DESC flag. It also allows filtering by catalog, schema or table name.

SELECT sh.name AS schema_name,
   i.name AS constraint_name,
   t.name AS table_name,
   c.name AS column_name,
   ic.key_ordinal AS column_position,
   ic.is_descending_key AS is_desc
FROM sys.indexes i
   INNER JOIN sys.index_columns ic
      ON i.index_id = ic.index_id AND i.object_id = ic.object_id
   INNER JOIN sys.tables AS t 
      ON t.object_id = i.object_id
   INNER JOIN sys.columns c
      ON t.object_id = c.object_id AND ic.column_id = c.column_id
   INNER JOIN sys.objects AS syso 
      ON syso.object_id = t.object_id AND syso.is_ms_shipped = 0 
   INNER JOIN sys.schemas AS sh
      ON sh.schema_id = t.schema_id 
   INNER JOIN information_schema.schemata sch
      ON sch.schema_name = sh.name
WHERE i.is_unique_constraint = 1
   -- AND sch.catalog_name = 'EmployeesQX'
   -- AND sh.name = 'dbo'
ORDER BY sh.name, i.name, ic.key_ordinal;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionanakicView Question on Stackoverflow
Solution 1 - Sql ServerAndrewView Answer on Stackoverflow
Solution 2 - Sql ServerEd HarperView Answer on Stackoverflow
Solution 3 - Sql ServerKenny EvittView Answer on Stackoverflow
Solution 4 - Sql ServerSanjay JainView Answer on Stackoverflow
Solution 5 - Sql ServerStefan SteigerView Answer on Stackoverflow
Solution 6 - Sql ServerCristian ScutaruView Answer on Stackoverflow