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?
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?
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
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;
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)
)
;
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'
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;