I need to list/display all the clustered and non clustered indexes contained by a table.
How can I do that using SQL Server 2008 R2?
How about this:
SELECT
TableName = t.Name,
i.*
FROM
sys.indexes i
INNER JOIN
sys.tables t ON t.object_id = i.object_id
WHERE
T.Name = 'YourTableName'
If you need more information (like columns contained in the index, their datatype etc.) - you can expand your query to something like this:
SELECT
TableName = t.Name,
IndexName = i.Name,
IndexType = i.type_desc,
ColumnOrdinal = Ic.key_ordinal,
ColumnName = c.name,
ColumnType = ty.name
FROM
sys.indexes i
INNER JOIN
sys.tables t ON t.object_id = i.object_id
INNER JOIN
sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN
sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
INNER JOIN
sys.types ty ON c.system_type_id = ty.system_type_id
WHERE
t.name = 'YourTableName'
ORDER BY
t.Name, i.name, ic.key_ordinal
These system catalog views contain a wealth of information about your system....
Related
I want to find the tables with the most number of rows and exclude tables with bigint primary keys.
The query below runs very fast and seems to work, but how can I modify it to filter out the bigint tables? I could perhaps ignore row_counts that are larger than MAX_INT, but that does not work if a table is bigint but does not have a lot of rows yet.
SELECT SCHEMA_NAME(O.schema_id) + '.' +
O.Name As [Schema.TableName], SUM(P.rows) AS 'Total_RowCount'
FROM sys.objects O
INNER JOIN sys.partitions P ON O.object_id = P.object_id
WHERE O.type = 'U'
AND P.index_id<2
GROUP BY O.schema_id, O.Name
order by Total_RowCount desc
You can use a NOT EXISTS in the WHERE and do a lateral join to the sys.types object for the primary key column(s). I assume if a PK is made of multiple columns, and one of them is a bigint you want to omit it:
SELECT SCHEMA_NAME(o.schema_id) + '.' + o.name AS [Schema.TableName],
SUM(p.rows) AS Total_RowCount
FROM sys.objects o
INNER JOIN sys.partitions p ON o.object_id = p.object_id
WHERE o.type = 'U'
AND p.index_id < 2
AND NOT EXISTS (SELECT 1
FROM sys.indexes i
JOIN sys.index_columns ic ON o.object_id = ic.object_id
AND i.index_id = ic.index_id
JOIN sys.columns c ON o.object_id = c.object_id
AND ic.column_id = c.column_id
JOIN sys.types ct ON c.system_type_id = ct.system_type_id
WHERE o.object_id = i.object_id
AND i.is_primary_key = 1
AND ct.[name] = 'bigint')
GROUP BY o.schema_id,
o.name
ORDER BY Total_RowCount DESC;
I'm looking for a T-SQL script, which can verify that my indexes are named correctly.
PK_ for primary keys
UK_ for unique keys
IX_ for non clustered non unique indexes
UX_ for unique indexes
and furthermore, the naming of the index (the tricky part):
IX_Column1_Column2 - instead of IX_CrazyIndexWhichFixesPerformance
Someone out there with this type of script?
It is quite easily accomplished with use of the Object Catalog Views (sys.*).
It depends how you want to approach this - you can write a full blown procedure to check all these things. I don't have code that will do exactly the above but this should set you on the right track.
For the Primary Key Check, you can find primary keys that don't fit your naming scheme with:
SELECT distinct
i.name AS index_name,
i.object_id
from
sys.indexes i
where
i.is_primary_key = 1
and i.name not like 'PK_%'
It will be a question of using the sys.objects table to filter for the particular key constraint.
For columns, join through sys.index_columns and sys.columns:
SELECT distinct
c.name AS column_name,
i.name AS index_name,
i.object_id
from
sys.indexes i
inner join sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
inner join sys.columns c ON ic.object_id = c.object_id AND c.column_id = ic.column_id
As you will want to concatenate column names into one field, you will need to look into FOR XML PATH('')
This information plus careful manipulation of the naming conventions you require should allow you perform these checks.
I ended up with this - it may not be pretty but gets the job done for now :-)
WITH indexesCTE
AS
(
SELECT
t.name AS TableName
, i.name AS IndexName
, i.index_id AS IndexId
, ic.index_column_id AS ColumnId
, t.object_id AS TableId
, REPLACE(c.name, '_', '') AS ColumnName
, i.object_id AS IndexObjectId
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id and i.index_id = ic.index_id
INNER JOIN sys.columns c ON ic.object_id = c.object_id and ic.column_id = c.column_id
INNER JOIN sys.tables t ON i.object_id = t.object_id
WHERE
i.is_primary_key = 0
AND i.is_unique = 0
AND i.is_unique_constraint = 0
AND t.is_ms_shipped = 0
)
, indexNameProposal
AS
(
SELECT i.TableName
, i.IndexName AS CurrentIndexName
, 'IX' + STUFF((SELECT '_' + i2.ColumnName FROM indexesCTE i2 WHERE i2.IndexId = i.IndexId AND i.TableId = i2.TableId FOR XML PATH('')),1,0,'') AS IndexNameProposal
FROM indexesCTE i
GROUP BY i.TableName, i.IndexName, i.TableId, i.IndexId
)
SELECT
*
FROM indexNameProposal i
WHERE i.CurrentIndexName <> i.IndexNameProposal
In Microsoft SQL, if I want to get information about where a column with a certain column name appears in my database, I can run this query:
select * from information_schema.columns where column_name = 'XXXXX';
This query returns a wealth of information about the instances where a column with the name appears, but I don't see anything about referential constraints.
I've tried some other queries below, but none seem to yield the information I want:
select * from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
select * from INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
I want to write a query that would do something like this:
select table_schema, table_name from INFORMATION_SCHEMA.COLUMNS
where column_name = 'XXXXX' and IsPrimaryKey = 1;
Edit: It was suggested that this question duplicates a question about finding the primary key of a given table. This question is related, but different because I am starting out knowing the name of a column (which may occur in many tables) and I want to be able to tell if there is a table with a primary key column with the same name.
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(CONSTRAINT_SCHEMA + '.' + CONSTRAINT_NAME), 'IsPrimaryKey') = 1
AND COLUMN_NAME = 'ColumnName' AND TABLE_SCHEMA = 'SchemaName'
SELECT
s.name AS schema_name,
o.name AS table_name
--, *
FROM sys.objects o
join sys.schemas s on s.schema_id = o.schema_id
join sys.indexes i on i.object_id = o.object_id
join sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
join sys.columns c ON ic.object_id = c.object_id AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1
and i.name = 'XXXXX';
EDIT:
I wrote the first way to show that PKs aren't always single column but forgot to note that and remove the extra rows. Here is the version that returns a single result.
SELECT
s.name AS schema_name,
o.name AS table_name
--, *
FROM sys.objects o
join sys.schemas s on s.schema_id = o.schema_id
join sys.indexes i on i.object_id = o.object_id
--join sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
--join sys.columns c ON ic.object_id = c.object_id AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1
and i.name = 'XXXXX';
EDIT 2
The original question was a little unclear as pointed out by SqlZim. In case you want to ask by column name I have added that option. WARNING: This will return multiple tables if you have tables with the same column name as PK. This is most likely in larger databases and many compound keys (e.g. a financial system where something like FinancialYear is often part of many compound keys).
SELECT
s.name AS schema_name,
o.name AS table_name
--, *
FROM sys.objects o
join sys.schemas s on s.schema_id = o.schema_id
join sys.indexes i on i.object_id = o.object_id
join sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
join sys.columns c ON ic.object_id = c.object_id AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1
and c.name = 'PROGRAM_YEAR';
The following query returns a listing of all my database primary keys and additional columns.
SELECT *
FROM sysobjects AS s
WHERE xtype='pk'
None of the aforementioned additional columns are related to a primary key's identity, seed value, increment value, etc.
What query should I use, or how may I find all primary keys in a database and their identity and seed values?
UPDATED
(now uses identity_columns table instead of the IDENT_... functions)
SELECT object_name(i.object_id) tableName,
i.name indexName,
c.name columnName,
c.is_identity,
idc.seed_value,
idc.increment_value,
idc.last_value
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
LEFT OUTER JOIN sys.identity_columns idc ON idc.object_id = c.object_id AND idc.column_id = c.column_id
WHERE i.is_primary_key = 1
Here is an alternate answer b/c I combined selects and added create and modified dates for sorting and schema name for possible dupes between schemas b/c key names are unique:
SELECT schema_name = ( SELECT top 1 pk.CONSTRAINT_SCHEMA FROM information_schema.table_constraints pk INNER JOIN information_schema.key_column_usage c ON c.TABLE_NAME = pk.TABLE_NAME WHERE pk.CONSTRAINT_NAME like '%' + i.name + '%')
,object_name(i.object_id) tableName, i.name indexName, c.name columnName, c.is_identity
,ident_seed(object_name(i.object_id)) seed
,ident_incr(object_name(i.object_id)) increment
,ident_current(object_name(i.object_id)) lastAssignedId
,CreateDate = ( SELECT s.crdate FROM sysobjects s INNER JOIN (SELECT COUNT(1) cnt, xtype FROM sysobjects group by xtype) c ON s.xtype = c.xtype WHERE s.name = i.name)
,ModifiedDate = (SELECT s.refdate FROM sysobjects s INNER JOIN (SELECT COUNT(1) cnt, xtype FROM sysobjects group by xtype) c on s.xtype = c.xtype WHERE s.name = i.name)
FROM sys.indexes i
INNER JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1
ORDER BY ModifiedDate, CreateDate DESC
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;