SQL Server 2005 - Good SQL to create a data dictionary - sql-server-2005

I have to create a data dictionary in an existing database for all user tables within that database in SQL Server 2005.
Does anyone have a good piece of sql to use for this purpose. I am intending to add comments in myself after I have the details of the tables and columns.

I don't have the exact sql, but you will need to query the systables and syscolumns tables, which have all of the information you need to create the data dictionary.

I would use the "information schema" views. Here are 2 of the most useful views:
SELECT * FROM INFORMATION_SCHEMA.Tables
SELECT * FROM INFORMATION_SCHEMA.Columns

Instead of doing this yourself, you could take a look at some SQL Server documentation tools/scripts:
http://www.mssqltips.com/tip.asp?tip=1250
http://www.red-gate.com/products/SQL_Doc/index.htm
http://www.mssqltips.com/tip.asp?tip=1499

https://www.csvreader.com/posts/data_dictionary.php
SELECT
d.[primary key],
d.[foreign key],
CASE
WHEN LEN(d.[column]) = 0 THEN d.[table]
ELSE ''
END AS [table],
d.[column],
CAST(d.[description] AS VARCHAR(MAX)) AS [description],
d.[data type],
d.nullable,
d.[identity],
d.[default]
FROM
(
SELECT
'' AS [primary key],
'' AS [foreign key],
s.[name] AS [schema],
CASE
WHEN s.[name] = 'dbo' THEN t.[name]
ELSE s.[name] + '.' + t.[name]
END AS [table],
'' AS [column],
ISNULL(RTRIM(CAST(ep.[value] AS NVARCHAR(4000))), '') AS [description],
'' AS [data type],
'' AS nullable,
'' AS [identity],
'' AS [default],
NULL AS column_id
FROM
sys.tables t
INNER JOIN sys.schemas s ON
s.[schema_id] = t.[schema_id]
-- get description of table, if available
LEFT OUTER JOIN sys.extended_properties ep ON
ep.major_id = t.[object_id] AND
ep.minor_id = 0 AND
ep.name = 'MS_Description' AND
ep.class = 1
WHERE
t.is_ms_shipped = 0 AND
NOT EXISTS
(
SELECT *
FROM
sys.extended_properties ms
WHERE
ms.major_id = t.[object_id] AND
ms.minor_id = 0 AND
ms.class = 1 AND
ms.[name] = 'microsoft_database_tools_support'
)
UNION ALL
SELECT
CASE
WHEN pk.column_id IS NOT NULL THEN 'PK'
ELSE ''
END AS [primary key],
CASE
WHEN fk.primary_table IS NOT NULL
THEN fk.primary_table + '.' + fk.primary_column
ELSE ''
END AS [foreign key],
s.[name] AS [schema],
CASE
WHEN s.[name] = 'dbo' THEN t.[name]
ELSE s.[name] + '.' + t.[name]
END AS [table],
c.[name] AS [column],
ISNULL(RTRIM(CAST(ep.[value] AS NVARCHAR(4000))), '') AS [description],
CASE
WHEN uty.[name] IS NOT NULL THEN uty.[name]
ELSE ''
END +
CASE
WHEN uty.[name] IS NOT NULL AND sty.[name] IS NOT NULL THEN '('
ELSE ''
END +
CASE
WHEN sty.[name] IS NOT NULL THEN sty.[name]
ELSE ''
END +
CASE
WHEN sty.[name] IN ('char', 'nchar', 'varchar', 'nvarchar', 'binary', 'varbinary')
THEN '(' +
CASE
WHEN c.max_length = -1 THEN 'max'
ELSE
CASE
WHEN sty.[name] IN ('nchar', 'nvarchar')
THEN CAST(c.max_length / 2 AS VARCHAR(MAX))
ELSE
CAST(c.max_length AS VARCHAR(MAX))
END
END
+ ')'
WHEN sty.[name] IN ('numeric', 'decimal')
THEN '(' +
CAST(c.precision AS VARCHAR(MAX)) + ', ' + CAST(c.scale AS VARCHAR(MAX))
+ ')'
ELSE
''
END +
CASE
WHEN uty.[name] IS NOT NULL AND sty.[name] IS NOT NULL THEN ')'
ELSE ''
END AS [data type],
CASE
WHEN c.is_nullable = 1 THEN 'Y'
ELSE ''
END AS nullable,
CASE
WHEN c.is_identity = 1 THEN 'Y'
ELSE ''
END AS [identity],
ISNULL(dc.[definition], '') AS [default],
c.column_id
FROM
sys.columns c
INNER JOIN sys.tables t ON
t.[object_id] = c.[object_id]
INNER JOIN sys.schemas s ON
s.[schema_id] = t.[schema_id]
-- get name of user data type
LEFT OUTER JOIN sys.types uty ON
uty.system_type_id = c.system_type_id AND
uty.user_type_id = c.user_type_id AND
c.user_type_id <> c.system_type_id
-- get name of system data type
LEFT OUTER JOIN sys.types sty ON
sty.system_type_id = c.system_type_id AND
sty.user_type_id = c.system_type_id
-- get description of column, if available
LEFT OUTER JOIN sys.extended_properties ep ON
ep.major_id = t.[object_id] AND
ep.minor_id = c.column_id AND
ep.[name] = 'MS_Description' AND
ep.[class] = 1
-- get default's code text
LEFT OUTER JOIN sys.default_constraints dc ON
dc.parent_object_id = t.[object_id] AND
dc.parent_column_id = c.column_id
-- check for inclusion in primary key
LEFT OUTER JOIN
(
SELECT
ic.column_id,
i.[object_id]
FROM
sys.indexes i
INNER JOIN sys.index_columns ic ON
ic.index_id = i.index_id AND
ic.[object_id] = i.[object_id]
WHERE
i.is_primary_key = 1
) pk ON
pk.column_id = c.column_id AND
pk.[object_id] = t.[object_id]
-- check for inclusion in foreign key
LEFT OUTER JOIN
(
SELECT
CASE
WHEN s.[name] = 'dbo' THEN pk.[name]
ELSE s.[name] + '.' + pk.[name]
END AS primary_table,
pkc.[name] as primary_column,
fkc.parent_object_id,
fkc.parent_column_id
FROM
sys.foreign_keys fk
INNER JOIN sys.tables pk ON
fk.referenced_object_id = pk.[object_id]
INNER JOIN sys.schemas s ON
s.[schema_id] = pk.[schema_id]
INNER JOIN sys.foreign_key_columns fkc ON
fkc.constraint_object_id = fk.[object_id] AND
fkc.referenced_object_id = pk.[object_id]
INNER JOIN sys.columns pkc ON
pkc.[object_id] = pk.[object_id] AND
pkc.column_id = fkc.referenced_column_id
) fk ON
fk.parent_object_id = t.[object_id] AND
fk.parent_column_id = c.column_id
WHERE
t.is_ms_shipped = 0 AND
NOT EXISTS
(
SELECT *
FROM
sys.extended_properties ms
WHERE
ms.major_id = t.[object_id] AND
ms.minor_id = 0 AND
ms.class = 1 AND
ms.[name] = 'microsoft_database_tools_support'
)
) d
ORDER BY
d.[schema],
d.[table],
d.column_id;

Related

Get metadata from extended properties (SQL Server)

I am building a data dictionary and trying to get some info from the extended properties.
I have a script to add extended properties (working as expected).
EXEC sys.sp_addextendedproperty
#name=N'MS_Description',
#value=N'This column stores the bla bla bla.' ,
#level0type=N'SCHEMA',
#level0name=N'dbo', --Schema Name
#level1type=N'TABLE',
#level1name=N'my_super_crazy_table',--Table Name
#level2type=N'COLUMN',
#level2name=N'my_super_crazy_column'--Column Name
GO
Now I want to ideally be able to see when these are created/updated (bonus if I can see what user -- suser_sname())
My final query for the data dictionary is below:
SELECT tbl.name as [table_name],
clmns.name as [column_name],
exprop.value as [column_description]
-- exprop.*
FROM sys.tables AS tbl
INNER JOIN sys.all_columns AS clmns ON clmns.object_id=tbl.object_id
LEFT OUTER JOIN sys.extended_properties exprop ON exprop.major_id = clmns.object_id AND exprop.minor_id = clmns.column_id
WHERE (tbl.name IN ('my_super_crazy_table') and exprop.class = 1)
Output:
table_name | column_name | column_description
my_super_crazy_table|my_super_crazy_column|This column stores the bla bla bla.
Is there any other sys table that could give me the information I'm looking for?
Thanks
SQL Server doesn't currently store any information about when extended properties are added or updated, or by who.
There's quite a bit more logic that you'd probably eventually want to implement. Here's my current best script for it.
https://www.csvreader.com/posts/data_dictionary.sql
SELECT
d.[primary key],
d.[foreign key],
CASE
WHEN LEN(d.[column]) = 0 THEN d.[table]
ELSE ''
END AS [table],
d.[column],
CAST(d.[description] AS VARCHAR(MAX)) AS [description],
d.[data type],
d.nullable,
d.[identity],
d.[default]
FROM
(
SELECT
'' AS [primary key],
'' AS [foreign key],
s.[name] AS [schema],
CASE
WHEN s.[name] = 'dbo' THEN t.[name]
ELSE s.[name] + '.' + t.[name]
END AS [table],
'' AS [column],
ISNULL(RTRIM(CAST(ep.[value] AS NVARCHAR(4000))), '') AS [description],
'' AS [data type],
'' AS nullable,
'' AS [identity],
'' AS [default],
NULL AS column_id
FROM
sys.tables t
INNER JOIN sys.schemas s ON
s.[schema_id] = t.[schema_id]
-- get description of table, if available
LEFT OUTER JOIN sys.extended_properties ep ON
ep.major_id = t.[object_id] AND
ep.minor_id = 0 AND
ep.name = 'MS_Description' AND
ep.class = 1
WHERE
t.is_ms_shipped = 0 AND
NOT EXISTS
(
SELECT *
FROM
sys.extended_properties ms
WHERE
ms.major_id = t.[object_id] AND
ms.minor_id = 0 AND
ms.class = 1 AND
ms.[name] = 'microsoft_database_tools_support'
)
UNION ALL
SELECT
CASE
WHEN pk.column_id IS NOT NULL THEN 'PK'
ELSE ''
END AS [primary key],
CASE
WHEN fk.primary_table IS NOT NULL
THEN fk.primary_table + '.' + fk.primary_column
ELSE ''
END AS [foreign key],
s.[name] AS [schema],
CASE
WHEN s.[name] = 'dbo' THEN t.[name]
ELSE s.[name] + '.' + t.[name]
END AS [table],
c.[name] AS [column],
ISNULL(RTRIM(CAST(ep.[value] AS NVARCHAR(4000))), '') AS [description],
CASE
WHEN uty.[name] IS NOT NULL THEN uty.[name]
ELSE ''
END +
CASE
WHEN uty.[name] IS NOT NULL AND sty.[name] IS NOT NULL THEN '('
ELSE ''
END +
CASE
WHEN sty.[name] IS NOT NULL THEN sty.[name]
ELSE ''
END +
CASE
WHEN sty.[name] IN ('char', 'nchar', 'varchar', 'nvarchar', 'binary', 'varbinary')
THEN '(' +
CASE
WHEN c.max_length = -1 THEN 'max'
ELSE
CASE
WHEN sty.[name] IN ('nchar', 'nvarchar')
THEN CAST(c.max_length / 2 AS VARCHAR(MAX))
ELSE
CAST(c.max_length AS VARCHAR(MAX))
END
END
+ ')'
WHEN sty.[name] IN ('numeric', 'decimal')
THEN '(' +
CAST(c.precision AS VARCHAR(MAX)) + ', ' + CAST(c.scale AS VARCHAR(MAX))
+ ')'
ELSE
''
END +
CASE
WHEN uty.[name] IS NOT NULL AND sty.[name] IS NOT NULL THEN ')'
ELSE ''
END AS [data type],
CASE
WHEN c.is_nullable = 1 THEN 'Y'
ELSE ''
END AS nullable,
CASE
WHEN c.is_identity = 1 THEN 'Y'
ELSE ''
END AS [identity],
ISNULL(dc.[definition], '') AS [default],
c.column_id
FROM
sys.columns c
INNER JOIN sys.tables t ON
t.[object_id] = c.[object_id]
INNER JOIN sys.schemas s ON
s.[schema_id] = t.[schema_id]
-- get name of user data type
LEFT OUTER JOIN sys.types uty ON
uty.system_type_id = c.system_type_id AND
uty.user_type_id = c.user_type_id AND
c.user_type_id <> c.system_type_id
-- get name of system data type
LEFT OUTER JOIN sys.types sty ON
sty.system_type_id = c.system_type_id AND
sty.user_type_id = c.system_type_id
-- get description of column, if available
LEFT OUTER JOIN sys.extended_properties ep ON
ep.major_id = t.[object_id] AND
ep.minor_id = c.column_id AND
ep.[name] = 'MS_Description' AND
ep.[class] = 1
-- get default's code text
LEFT OUTER JOIN sys.default_constraints dc ON
dc.parent_object_id = t.[object_id] AND
dc.parent_column_id = c.column_id
-- check for inclusion in primary key
LEFT OUTER JOIN
(
SELECT
ic.column_id,
i.[object_id]
FROM
sys.indexes i
INNER JOIN sys.index_columns ic ON
ic.index_id = i.index_id AND
ic.[object_id] = i.[object_id]
WHERE
i.is_primary_key = 1
) pk ON
pk.column_id = c.column_id AND
pk.[object_id] = t.[object_id]
-- check for inclusion in foreign key
LEFT OUTER JOIN
(
SELECT
CASE
WHEN s.[name] = 'dbo' THEN pk.[name]
ELSE s.[name] + '.' + pk.[name]
END AS primary_table,
pkc.[name] as primary_column,
fkc.parent_object_id,
fkc.parent_column_id
FROM
sys.foreign_keys fk
INNER JOIN sys.tables pk ON
fk.referenced_object_id = pk.[object_id]
INNER JOIN sys.schemas s ON
s.[schema_id] = pk.[schema_id]
INNER JOIN sys.foreign_key_columns fkc ON
fkc.constraint_object_id = fk.[object_id] AND
fkc.referenced_object_id = pk.[object_id]
INNER JOIN sys.columns pkc ON
pkc.[object_id] = pk.[object_id] AND
pkc.column_id = fkc.referenced_column_id
) fk ON
fk.parent_object_id = t.[object_id] AND
fk.parent_column_id = c.column_id
WHERE
t.is_ms_shipped = 0 AND
NOT EXISTS
(
SELECT *
FROM
sys.extended_properties ms
WHERE
ms.major_id = t.[object_id] AND
ms.minor_id = 0 AND
ms.class = 1 AND
ms.[name] = 'microsoft_database_tools_support'
)
) d
ORDER BY
d.[schema],
d.[table],
d.column_id;

Select column names and top 1 records along, dynamically

I was trying to select top 1 column value from the table to have a glimpse of the data, based on the output
(i.e. equivalently,
SELECT c.name FROM st.Name
This query retrieves column names and their data type along with the tables they're in. I am looking for an additional column that shows top 1 record from the columns.
SELECT
st.name 'Table Name',
c.name 'Column Name',
t.name 'Data Type'
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_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
LEFT OUTER JOIN sys.tables st ON st.object_id = i.object_id
I have been trying to use a dynamic sql, but as it should put the table name in a single quotation as a string, it couldn't work; when I try to avoid that, it just displays the declared variable.
Any idea is much appreciated. Thanks
So the way this works is basically creates a bunch of selects like:
SELECT 'dbo' AS [Schema Name]
, 'Table1' AS [Table Name]
, 'Id' AS [Column Name]
, 'bigint' AS [Data Type]
, (SELECT TOP 1 CONVERT(NVARCHAR(MAX), Id) FROM [dbo].[Table1]) AS [Top 1 Value]
UNION ALL
-- Another table
Values are converted into NVARCHAR(MAX) because column type in an union has to match and I guess that's the best bet.
Here goes:
DECLARE #query NVARCHAR(MAX) = ''
SELECT #Query +=
'SELECT ' + '''' + sch.name + '''' + ' AS [Schema Name],' + CHAR(13)+CHAR(10)
+ '''' + st.name + '''' + ' AS [Table Name],' + CHAR(13)+CHAR(10)
+ '''' + c.name + '''' + ' AS [Column Name],' + CHAR(13)+CHAR(10)
+ '''' + t.name + '''' + ' AS [Data Type],' + CHAR(13)+CHAR(10)
+ '(SELECT TOP 1 CONVERT(NVARCHAR(MAX), ' + c.name + ') FROM ' + QUOTENAME(sch.name) + '.' + QUOTENAME(st.name) + ') AS [Top 1 Value] ' + CHAR(13)+CHAR(10)
+ 'UNION ALL'+CHAR(13)+CHAR(10)
FROM sys.columns c
JOIN sys.types t ON c.user_type_id = t.user_type_id
JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
JOIN sys.tables st ON st.object_id = i.object_id
JOIN sys.schemas sch ON sch.schema_id = st.schema_id
-- Get rid of trailing UNION ALL
SET #Query = LEFT(#Query, LEN(#Query) - LEN('UNION ALLxx'))
PRINT #query
EXEC sp_executesql #query
Consider running with TOP 10 or some such first to make sure it's producing the right results.
you could use a while loop with d sql
-
--drop table #temp
SELECT
CONCAT(s.name,'.',st.name) 'Table Name',
c.name 'Column Name',
t.name 'Data Type',
CAST(null AS datetime) as IND,
cast('' AS varchar(max)) data
INTO #temp
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_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
INNER JOIN sys.tables st ON st.object_id = i.object_id
INNER JOIN sys.schemas s ON s.schema_id = st.schema_id
declare
#TableName varchar(255),
#ColumnName Varchar(255),
#sql varchar(max)
WHILE (SELECT count(*) FROM #temp where IND is null) > 0
begin
SELECT TOP 1
#TableName = [Table Name]
,#ColumnName = [Column Name]
FROM #temp
WHERE IND IS NULL
SET #sql =
'update #temp
set data = (SELECT top 1 [' + #ColumnName + '] from ' + #TableName + '),
IND = getdate()
where [Table Name] = ''' + #TableName + ''' and [Column Name] = ''' + #ColumnName + ''''
exec(#sql)
end
SELECT *
FROM #temp

How to list all indexes and index related objects in all databases (SQL Server) using cursor

I wanted to list all index and index related objects in all of my databases (in my case 48) and decided to use cursor. I have found a code on stack overflow that does exactly the same thing for a given one database but modified to use cursor so I can have the same info fol all all databases.The problem is the code seems okay but when i run it gives me error.How do i fix this code and make it run? Thanks
-- SQL query to collect all indexes and related objects
-- instance level from multiple databases
DECLARE #db_nm VARCHAR(250), #sql NVARCHAR(1000)
DECLARE #results TABLE
(
[database_name] sysname,
[table_view] sysname,
[object_type] sysname,
[constraint_type] sysname,
[constraint_name] sysname,
[columns] sysname,
[index_name] sysname,
[index_type] sysname
);
DECLARE db CURSOR LOCAL FAST_FORWARD FOR
SELECT db.name
FROM master.sys.databases AS db
WHERE db.name NOT IN ('master', 'tempdb', 'model', 'msdb')
AND db.state_desc = 'ONLINE' --system db you're probably not looking for info in
OPEN db ;
FETCH NEXT FROM db INTO #db_nm;
WHILE ##fetch_status = 0
BEGIN
-- select * from sys.objects t
-- select schema_name(t.schema_id) + '.' + t.[name] as table_view from ---sys.objects t
SET #sql= 'select ''' + #db_nm + ''' AS [database_name], schema_name(t.schema_id) + t.[name] as [table_view],
case when t.[type] = 'U' Then 'Table'
case when t.[type] = 'V' then 'View'
end as [object_type],
case when c.[type] = 'PK' then 'Primary key'
when c.[type] = 'UQ' then 'Unique constraint'
when i.[type] = 1 then 'Unique clustered index'
when i.type = 2 then 'Unique index'
end as [constraint_type],
c.[name] as [constraint_name],
substring(column_names, 1, len(column_names)-1) as [columns],
i.[name] as [index_name],
case when i.[type] = 1 then 'Clustered index'
when i.type = 2 then 'Index'
end as [index_type]
from [' + #db_nm + '].sys.objects t
left outer join [' + #db_nm + '].sys.indexes i
on t.object_id = i.object_id
left outer join [' + #db_nm + '].sys.key_constraints c
on i.object_id = c.parent_object_id
and i.index_id = c.unique_index_id
cross apply (select col.[name] + ', '
from [' + #db_nm + '].sys.index_columns ic
inner join [' + #db_nm + '].sys.columns col
on ic.object_id = col.object_id
and ic.column_id = col.column_id
where ic.object_id = t.object_id
and ic.index_id = i.index_id
order by col.column_id
for xml path ('') ) D (column_names)
where is_unique = 1
and t.is_ms_shipped <> 1
order by schema_name(t.schema_id) + '.' + t.[name]';
INSERT INTO #results
EXEC (#sql)
FETCH NEXT FROM db INTO #db_nm;
END;
CLOSE db;
DEALLOCATE db;
-- select * into #temp from #results
SELECT * FROM #results;
--Here is the code that fits my need for one given database but want to loop it for all databases
SELECT
schema_name(t.schema_id) + '.' + t.[name] as table_view,
CASE WHEN t.[type] = 'U' THEN 'Table'
WHEN t.[type] = 'V' THEN 'View'
END AS [object_type],
CASE WHEN c.[type] = 'PK' THEN 'Primary key'
WHEN c.[type] = 'UQ' THEN 'Unique constraint'
WHEN i.[type] = 1 THEN 'Unique clustered index'
WHEN i.type = 2 THEN 'Unique index'
END AS constraint_type,
c.[name] AS constraint_name,
substring(column_names, 1, len(column_names)-1) as [columns],
i.[name] as index_name,
case when i.[type] = 1 then 'Clustered index'
when i.type = 2 then 'Index'
end as index_type
from sys.objects t
left outer join sys.indexes i
on t.object_id = i.object_id
left outer join sys.key_constraints c
on i.object_id = c.parent_object_id
and i.index_id = c.unique_index_id
cross apply (select col.[name] + ', '
from sys.index_columns ic
inner join sys.columns col
on ic.object_id = col.object_id
and ic.column_id = col.column_id
where ic.object_id = t.object_id
and ic.index_id = i.index_id
order by col.column_id
for xml path ('') ) D (column_names)
where is_unique = 1
and t.is_ms_shipped <> 1
order by schema_name(t.schema_id) + '.' + t.[name]

SQL server query to get the list of columns in a table along with Data types, NOT NULL, and PRIMARY KEY constraints

I need to write a query on SQL server to get the list of columns in a particular table, its associated data types (with length) and if they are not null. And I have managed to do this much.
But now i also need to get, in the same table, against a column - TRUE if that column is a primary key.
How do i do this?
My expected output is:
Column name | Data type | Length | isnull | Pk
To avoid duplicate rows for some columns, use user_type_id instead of system_type_id.
SELECT
c.name 'Column Name',
t.Name 'Data type',
c.max_length 'Max Length',
c.precision ,
c.scale ,
c.is_nullable,
ISNULL(i.is_primary_key, 0) 'Primary Key'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.user_type_id = t.user_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('YourTableName')
Just replace YourTableName with your actual table name - works for SQL Server 2005 and up.
In case you are using schemas, replace YourTableName by YourSchemaName.YourTableName where YourSchemaName is the actual schema name and YourTableName is the actual table name.
The stored procedure sp_columns returns detailed table information.
exec sp_columns MyTable
You could use the query:
select COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH,
NUMERIC_PRECISION, DATETIME_PRECISION,
IS_NULLABLE
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME='TableName'
to get all the metadata you require except for the Pk information.
In SQL 2012 you can use:
EXEC sp_describe_first_result_set N'SELECT * FROM [TableName]'
This will give you the column names along with their properties.
Try this:
select COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, IS_NULLABLE
from INFORMATION_SCHEMA.COLUMNS IC
where TABLE_NAME = 'tablename' and COLUMN_NAME = 'columnname'
To ensure you obtain the right length you would need to consider unicode types as a special case. See code below.
For further information see: https://msdn.microsoft.com/en-us/library/ms176106.aspx
SELECT
c.name 'Column Name',
t.name,
t.name +
CASE WHEN t.name IN ('char', 'varchar','nchar','nvarchar') THEN '('+
CASE WHEN c.max_length=-1 THEN 'MAX'
ELSE CONVERT(VARCHAR(4),
CASE WHEN t.name IN ('nchar','nvarchar')
THEN c.max_length/2 ELSE c.max_length END )
END +')'
WHEN t.name IN ('decimal','numeric')
THEN '('+ CONVERT(VARCHAR(4),c.precision)+','
+ CONVERT(VARCHAR(4),c.Scale)+')'
ELSE '' END
as "DDL name",
c.max_length 'Max Length in Bytes',
c.precision ,
c.scale ,
c.is_nullable,
ISNULL(i.is_primary_key, 0) 'Primary Key'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.user_type_id = t.user_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('YourTableName')
I am a little bit surprised nobody mentioned
sp_help 'mytable'
Expanding on Alex's answer, you can do this to get the PK constraint
Select C.COLUMN_NAME, C.DATA_TYPE, C.CHARACTER_MAXIMUM_LENGTH, C.NUMERIC_PRECISION, C.IS_NULLABLE, TC.CONSTRAINT_NAME
From INFORMATION_SCHEMA.COLUMNS As C
Left Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As TC
On TC.TABLE_SCHEMA = C.TABLE_SCHEMA
And TC.TABLE_NAME = C.TABLE_NAME
And TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
Where C.TABLE_NAME = 'Table'
I must have missed that you want a flag to determine if the given column was part of the PK instead of the name of the PK constraint. For that you would use:
Select C.COLUMN_NAME, C.DATA_TYPE, C.CHARACTER_MAXIMUM_LENGTH
, C.NUMERIC_PRECISION, C.NUMERIC_SCALE
, C.IS_NULLABLE
, Case When Z.CONSTRAINT_NAME Is Null Then 0 Else 1 End As IsPartOfPrimaryKey
From INFORMATION_SCHEMA.COLUMNS As C
Outer Apply (
Select CCU.CONSTRAINT_NAME
From INFORMATION_SCHEMA.TABLE_CONSTRAINTS As TC
Join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE As CCU
On CCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
Where TC.TABLE_SCHEMA = C.TABLE_SCHEMA
And TC.TABLE_NAME = C.TABLE_NAME
And TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
And CCU.COLUMN_NAME = C.COLUMN_NAME
) As Z
Where C.TABLE_NAME = 'Table'
Throwing another answer into the ring, this will give you those columns and more:
SELECT col.TABLE_CATALOG AS [Database]
, col.TABLE_SCHEMA AS Owner
, col.TABLE_NAME AS TableName
, col.COLUMN_NAME AS ColumnName
, col.ORDINAL_POSITION AS OrdinalPosition
, col.COLUMN_DEFAULT AS DefaultSetting
, col.DATA_TYPE AS DataType
, col.CHARACTER_MAXIMUM_LENGTH AS MaxLength
, col.DATETIME_PRECISION AS DatePrecision
, CAST(CASE col.IS_NULLABLE
WHEN 'NO' THEN 0
ELSE 1
END AS bit)AS IsNullable
, COLUMNPROPERTY(OBJECT_ID('[' + col.TABLE_SCHEMA + '].[' + col.TABLE_NAME + ']'), col.COLUMN_NAME, 'IsIdentity')AS IsIdentity
, COLUMNPROPERTY(OBJECT_ID('[' + col.TABLE_SCHEMA + '].[' + col.TABLE_NAME + ']'), col.COLUMN_NAME, 'IsComputed')AS IsComputed
, CAST(ISNULL(pk.is_primary_key, 0)AS bit)AS IsPrimaryKey
FROM INFORMATION_SCHEMA.COLUMNS AS col
LEFT JOIN(SELECT SCHEMA_NAME(o.schema_id)AS TABLE_SCHEMA
, o.name AS TABLE_NAME
, c.name AS COLUMN_NAME
, i.is_primary_key
FROM sys.indexes AS i JOIN sys.index_columns AS ic ON i.object_id = ic.object_id
AND i.index_id = ic.index_id
JOIN sys.objects AS o ON i.object_id = o.object_id
LEFT JOIN sys.columns AS c ON ic.object_id = c.object_id
AND c.column_id = ic.column_id
WHERE i.is_primary_key = 1)AS pk ON col.TABLE_NAME = pk.TABLE_NAME
AND col.TABLE_SCHEMA = pk.TABLE_SCHEMA
AND col.COLUMN_NAME = pk.COLUMN_NAME
WHERE col.TABLE_NAME = 'YourTableName'
AND col.TABLE_SCHEMA = 'dbo'
ORDER BY col.TABLE_NAME, col.ORDINAL_POSITION;
SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM information_schema.columns WHERE table_name = '<name_of_table_or_view>'
Run SELECT * in the above statement to see what information_schema.columns returns.
This question has been previously answered - https://stackoverflow.com/a/11268456/6169225
wite the table name in the query editor select the name and press Alt+F1 and it will bring all the information of the table.
IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME = 'Table')
BEGIN
SELECT COLS.COLUMN_NAME, COLS.DATA_TYPE, COLS.CHARACTER_MAXIMUM_LENGTH,
(SELECT 'Yes' FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
ON COLS.TABLE_NAME = TC.TABLE_NAME
AND TC.CONSTRAINT_TYPE = 'PRIMARY KEY'
AND KCU.TABLE_NAME = TC.TABLE_NAME
AND KCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
AND KCU.COLUMN_NAME = COLS.COLUMN_NAME) AS KeyX
FROM INFORMATION_SCHEMA.COLUMNS COLS WHERE TABLE_NAME = 'Table' ORDER BY KeyX DESC, COLUMN_NAME
END
marc_s's answer is good but it has a flaw if the primary key column(s) appear in other indexes in that those columns will appear more than once. e.g.
Demo:
create table dbo.DummyTable
(
id int not null identity(0,1) primary key,
Msg varchar(80) null
);
create index NC_DummyTable_id ON DummyTable(id);
Here's my stored procedure to solve problem:
create or alter procedure dbo.GetTableColumns
(
#schemaname nvarchar(128),
#tablename nvarchar(128)
)
AS
BEGIN
SET NOCOUNT ON;
with ctePKCols as
(
select
i.object_id,
ic.column_id
from
sys.indexes i
join sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
where
i.is_primary_key = 1
)
SELECT
c.name AS column_name,
t.name AS typename,
c.max_length AS MaxLength,
c.precision,
c.scale,
c.is_nullable,
is_primary_key = CASE WHEN ct.column_id IS NOT NULL THEN 1 ELSE 0 END
FROM
sys.columns c
JOIN sys.types t ON t.user_type_id = c.user_type_id
LEFT JOIN ctePKCols ct ON ct.column_id = c.column_id AND ct.object_id = c.object_id
WHERE
c.object_ID = OBJECT_ID(quotename(#schemaname) + '.' + quotename(#tablename))
END
GO
exec dbo.GetTableColumns 'dbo', 'DummyTable'
Find combine result for Datatype and Length and is nullable in form of "NULL" and "Not null" Use below query.
SELECT c.name AS 'Column Name',
t.name + '(' + cast(c.max_length as varchar(50)) + ')' As 'DataType',
case
WHEN c.is_nullable = 0 then 'null' else 'not null'
END AS 'Constraint'
FROM sys.columns c
JOIN sys.types t
ON c.user_type_id = t.user_type_id
WHERE c.object_id = Object_id('TableName')
you will find result as shown below.
Thank you.
Query : EXEC SP_DESCRIBE_FIRST_RESULT_SET N'SELECT ANNUAL_INCOME FROM
[DB_NAME].[DBO].[EMPLOYEE]'
NOTE: IN SOME IDE BEFORE SELECT N IS WORKING OR, IN SOME IDE WITHOUT N IS WORKING
select
c.name as [column name],
t.name as [type name],
tbl.name as [table name]
from sys.columns c
inner join sys.types t
on c.system_type_id = t.system_type_id
inner join sys.tables tbl
on c.object_id = tbl.object_id
where
c.object_id = OBJECT_ID('YourTableName1')
and
t.name like '%YourSearchDataType%'
union
(select
c.name as [column name],
t.name as [type name],
tbl.name as [table name]
from sys.columns c
inner join sys.types t
on c.system_type_id = t.system_type_id
inner join sys.tables tbl
on c.object_id = tbl.object_id
where
c.object_id = OBJECT_ID('YourTableName2')
and
t.name like '%YourSearchDataType%')
union
(select
c.name as [column name],
t.name as [type name],
tbl.name as [table name]
from sys.columns c
inner join sys.types t
on c.system_type_id = t.system_type_id
inner join sys.tables tbl
on c.object_id = tbl.object_id
where
c.object_id = OBJECT_ID('YourTableName3')
and
t.name like '%YourSearchDataType%')
order by tbl.name
To search which column is in which table based on your search data type for three different table in one database. This query is expandable to 'n' tables.
Throwing another way to tackle the problem in SQL server.
My little script here should return the Column Name, Data Type, Is Nullable, Constraints, and Indexes Names.
You can also include any additional columns such as precision, scale...
(You will need to replace the DB name, Schema Name, and Table Name with yours)
.The Columns are returned in the same order you would get from 'select * from table'
USE DBA -- Replace Database Name with yours
DECLARE #SCHEMA VARCHAR(MAX)
DECLARE #TABLE_NAME VARCHAR(MAX)
DECLARE #SCHEMA_TABLE_NAME VARCHAR(MAX)
SET #SCHEMA = REPLACE(REPLACE('[SCHEMA NAME]', '[', ''), ']', '')--Replace Schema Name with yours
SET #TABLE_NAME = REPLACE(REPLACE('[TABLE NAME]', '[', ''), ']', '') --' Replace Table Name with yours
SET #SCHEMA_TABLE_NAME = #SCHEMA + '.' + #TABLE_NAME;
WITH SchemaColumns
AS (
SELECT C.COLUMN_NAME,
IS_NULLABLE,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
C.ORDINAL_POSITION
FROM INFORMATION_SCHEMA.COLUMNS AS C
WHERE C.TABLE_SCHEMA = #SCHEMA
AND C.TABLE_NAME = #TABLE_NAME
),
SchemaConstraints
AS (
SELECT CN.COLUMN_NAME,
CC.CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS CC
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS CN ON CC.CONSTRAINT_NAME = CC.CONSTRAINT_NAME
WHERE CC.TABLE_SCHEMA = #SCHEMA
AND CC.TABLE_NAME = #TABLE_NAME
),
SchemaIndex
AS (
SELECT I.name AS index_name,
COL_NAME(IC.object_id, IC.column_id) AS column_name,
IC.index_column_id,
IC.key_ordinal,
IC.is_included_column
FROM sys.indexes AS i
INNER JOIN sys.index_columns AS IC ON I.object_id = IC.object_id
AND I.index_id = IC.index_id
WHERE I.object_id = OBJECT_ID(#SCHEMA_TABLE_NAME)
)
SELECT ISNULL(SchemaColumns.COLUMN_NAME, '') "Column Name",
CASE
WHEN SchemaColumns.CHARACTER_MAXIMUM_LENGTH IS NULL
THEN UPPER(ISNULL(SchemaColumns.DATA_TYPE, ''))
ELSE CONCAT (
UPPER(ISNULL(SchemaColumns.DATA_TYPE, '')),
'(',
CAST(SchemaColumns.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(50)),
')'
)
END "Data Type",
SchemaColumns.IS_NULLABLE "Is Nullable",
ISNULL(SchemaConstraints.CONSTRAINT_TYPE, '-') "Constraints",
ISNULL(STRING_AGG(CONVERT(NVARCHAR(max), SchemaIndex.INDEX_NAME), CHAR(13)), '-') "Indexes Names"
FROM SchemaColumns
LEFT JOIN SchemaConstraints ON SchemaConstraints.COLUMN_NAME = SchemaColumns.COLUMN_NAME
LEFT JOIN SchemaIndex ON SchemaColumns.COLUMN_NAME = SchemaIndex.COLUMN_NAME
GROUP BY SchemaColumns.COLUMN_NAME,
SchemaColumns.DATA_TYPE,
SchemaColumns.CHARACTER_MAXIMUM_LENGTH,
SchemaColumns.IS_NULLABLE,
SchemaConstraints.CONSTRAINT_TYPE,
SchemaColumns.ORDINAL_POSITION
ORDER BY SchemaColumns.ORDINAL_POSITION
SELECT
T.NAME AS [TABLE NAME]
,C.NAME AS [COLUMN NAME]
,P.NAME AS [DATA TYPE]
,P.MAX_LENGTH AS [Max_SIZE]
,C.[max_length] AS [ActualSizeUsed]
,CAST(P.PRECISION AS VARCHAR) +'/'+ CAST(P.SCALE AS VARCHAR) AS [PRECISION/SCALE]
FROM SYS.OBJECTS AS T
JOIN SYS.COLUMNS AS C
ON T.OBJECT_ID = C.OBJECT_ID
JOIN SYS.TYPES AS P
ON C.SYSTEM_TYPE_ID = P.SYSTEM_TYPE_ID
AND C.[user_type_id] = P.[user_type_id]
WHERE T.TYPE_DESC='USER_TABLE'
AND T.name = 'InventoryStatus'
ORDER BY 2
There is no primary key here, but this can help other users who would just like to have a table name with field name and basic field properties
USE [**YourDB**]
GO
SELECT tbl.name, fld.[Column Name],fld.[Constraint],fld.DataType
FROM sys.all_objects as tbl left join
(SELECT c.OBJECT_ID, c.name AS 'Column Name',
t.name + '(' + cast(c.max_length as varchar(50)) + ')' As 'DataType',
case
WHEN c.is_nullable = 0 then 'null' else 'not null'
END AS 'Constraint'
FROM sys.columns c
JOIN sys.types t
ON c.user_type_id = t.user_type_id
) as fld on tbl.OBJECT_ID = fld.OBJECT_ID
WHERE ( tbl.[type]='U' and tbl.[is_ms_shipped] = 0)
ORDER BY tbl.[name],fld.[Column Name]
GO
I just made marc_s "presentation ready":
SELECT
c.name 'Column Name',
t.name 'Data type',
IIF(t.name = 'nvarchar', c.max_length / 2, c.max_length) 'Max Length',
c.precision 'Precision',
c.scale 'Scale',
IIF(c.is_nullable = 0, 'No', 'Yes') 'Nullable',
IIF(ISNULL(i.is_primary_key, 0) = 0, 'No', 'Yes') 'Primary Key'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.user_type_id = t.user_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('YourTableName')

Generate CREATE scripts for a list of indexes

As part of a collation changing exercise, I have a list of indexes (122) that needs to be dropped and then re-created. How can I re-create these indexes without having to go through the GUI and scripting it to a query window each time?
My list of indexes is obtained from this script
WITH indexCTE AS
(
SELECT Table_Name, Column_Name, Collation_Name
FROM information_schema.columns
WHERE Collation_Name IS NOT NULL AND Collation_Name = 'Modern_Spanish_CI_AS'
),
indexCTE2 AS
(
SELECT i.Name [Index Name], OBJECT_NAME(i.object_ID) [Table Name], c.Name [Column Name]
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.columns c ON ic.column_id = c.column_id AND ic.object_id = c.OBJECT_ID
WHERE EXISTS (SELECT 1 FROM indexCTE t1 WHERE t1.Table_Name = OBJECT_NAME(i.object_ID) AND t1.Column_Name = c.Name)
) SELECT * FROM indexCTE2
As you can probably tell, I'm still a Jr. DBA so please be patient with me!
Thanks!
You're pretty close, I'd say - I tried this, can you verify if this works for you and shows you the expected 122 indices to be recreated??
UPDATE: added functionality to determine CLUSTERED vs. NONCLUSTERED index type, and to add INCLUDEd columns to the index definition.
WITH indexCTE AS
(
SELECT DISTINCT
i.index_id, i.name, i.object_id
FROM
sys.indexes i
INNER JOIN
sys.index_columns ic
ON i.index_id = ic.index_id AND i.object_id = ic.object_id
WHERE
EXISTS (SELECT * FROM sys.columns c
WHERE c.collation_name = 'Modern_Spanish_CI_AS'
AND c.column_id = ic.column_id AND c.object_id = ic.object_id)
),
indexCTE2 AS
(
SELECT
indexCTE.name 'IndexName',
OBJECT_NAME(indexCTE.object_ID) 'TableName',
CASE indexCTE.index_id
WHEN 1 THEN 'CLUSTERED'
ELSE 'NONCLUSTERED'
END AS 'IndexType',
(SELECT DISTINCT c.name + ','
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 0
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
) ixcols,
ISNULL(
(SELECT DISTINCT c.name + ','
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 1
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
), '') includedcols
FROM
indexCTE
)
SELECT
'CREATE ' + IndexType + ' INDEX ' + IndexName + ' ON ' + TableName +
'(' + SUBSTRING(ixcols, 1, LEN(ixcols)-1) +
CASE LEN(includedcols)
WHEN 0 THEN ')'
ELSE ') INCLUDE (' + SUBSTRING(includedcols, 1, LEN(includedcols)-1) + ')'
END
FROM
indexCTE2
ORDER BY
TableName, IndexName
Do you get the CREATE INDEX statements you're looking for??
Marc
Great script Marc.
The only thing I think it is missing is the ascending or descending order indicator on each column. I have amended your script to include a case statement for the indexed columns to add in ASC or DESC depending on the is_descending_key column of the sys.index_columns view.
WITH indexCTE AS
(
SELECT DISTINCT
i.index_id, i.name, i.object_id
FROM
sys.indexes i
INNER JOIN
sys.index_columns ic
ON i.index_id = ic.index_id AND i.object_id = ic.object_id
WHERE
EXISTS (SELECT * FROM sys.columns c
WHERE
c.collation_name = 'Modern_Spanish_CI_AS'
AND c.column_id = ic.column_id AND c.object_id = ic.object_id)
),
indexCTE2 AS
(
SELECT
indexCTE.name 'IndexName',
OBJECT_NAME(indexCTE.object_ID) 'TableName',
CASE indexCTE.index_id
WHEN 1 THEN 'CLUSTERED'
ELSE 'NONCLUSTERED'
END AS 'IndexType',
(SELECT CASE WHEN ic.is_descending_key = 1 THEN c.name + ' DESC ,'
ELSE c.name + ' ASC ,'
END
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 0
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
) ixcols,
ISNULL(
(SELECT DISTINCT c.name + ','
FROM
sys.columns c
INNER JOIN
sys.index_columns ic
ON c.object_id = ic.object_id AND ic.column_id = c.column_id AND ic.Is_Included_Column = 1
WHERE
indexCTE.OBJECT_ID = ic.object_id
AND indexCTE.index_id = ic.index_id
FOR XML PATH('')
), '') includedcols
FROM
indexCTE
)
SELECT
'CREATE ' + IndexType + ' INDEX ' + IndexName + ' ON ' + TableName +
'(' + SUBSTRING(ixcols, 1, LEN(ixcols)-1) +
CASE LEN(includedcols)
WHEN 0 THEN ')'
ELSE ') INCLUDE (' + SUBSTRING(includedcols, 1, LEN(includedcols)-1) + ')'
END
FROM
indexCTE2
ORDER BY
TableName, IndexName
DECLARE #T_IndexInfo TABLE
(
IndID NVARCHAR(128),
ObjectID NVARCHAR(128),
ColID NVARCHAR(128),
IndexName NVARCHAR(128),
TableName NVARCHAR(128),
ColumnName NVARCHAR(128),
KeyNo NVARCHAR(128),
ColType NVARCHAR(128)
)
INSERT INTO #T_IndexInfo
SELECT I.IndID,
SO.ID AS 'ObjectID',
SK.ColID,
I.Name AS 'IndexName',
SO.Name AS 'TableName',
SC.Name AS 'ColumnName',
Sk.KeyNo,
CASE WHEN Sk.KeyNo = 0 THEN 'Include'
ELSE 'Normal'
END AS 'ColType'
FROM sys.sysindexes I
INNER JOIN sys.sysobjects SO ON SO.ID = I.ID
AND SO.xtype = 'U'
INNER JOIN sys.sysindexkeys SK ON SK.IndID = I.IndID
AND SO.ID = SK.ID
INNER JOIN sys.syscolumns SC ON SC.ID = SO.ID
AND SC.ColID = SK.ColID
WHERE I.IndID > 0
AND I.IndID < 255
AND ( I.Status & 64 ) = 0
-- AND ( I.status & 2048 ) <> 2048 /******** comment this if PK's also need to be recreated *****/
ORDER BY SO.Name,
I.Name
DECLARE #T_Final TABLE
(
TableName NVARCHAR(128),
IndexName NVARCHAR(128),
NormalColumns NVARCHAR(MAX),
IncludedColumns NVARCHAR(MAX)
)
INSERT INTO #T_Final
SELECT DISTINCT
TableName,
IndexName,
STUFF(( SELECT ',[' + ColumnName + ']'
FROM #T_IndexInfo
WHERE IndID = I.IndID
AND ObjectID = I.ObjectID
AND ColType = 'Normal'
ORDER BY KeyNo
FOR
XML PATH('')
), 1, 1, '') AS 'NormalColumns',
STUFF(( SELECT ',[' + ColumnName + ']'
FROM #T_IndexInfo
WHERE IndID = I.IndID
AND ObjectID = I.ObjectID
AND ColType = 'Include'
FOR
XML PATH('')
), 1, 1, '') AS 'IncludedColumns'
FROM #T_IndexInfo I;
WITH indexCTE AS
(
SELECT Table_Name, Column_Name --, Collation_Name
FROM information_schema.columns
WHERE Collation_Name IS NOT NULL AND Collation_Name = 'Modern_Spanish_CI_AS'
),
indexCTE2 AS
(
SELECT i.Name [Index Name], OBJECT_NAME(i.object_ID) [Table Name], c.Name [Column Name]
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.columns c ON ic.column_id = c.column_id AND ic.object_id = c.OBJECT_ID
WHERE EXISTS (SELECT 1 FROM indexCTE t1 WHERE t1.Table_Name = OBJECT_NAME(i.object_ID) AND t1.Column_Name = c.Name)
)
SELECT IndexName, TableName, NormalColumns, IncludedColumns
INTO #temp1
FROM #T_Final z INNER JOIN indexCTE2 x ON z.IndexName = x.[Index Name]
-- To generate CREATE INDEX SCRIPT
SELECT 'CREATE INDEX [' + IndexName + '] ON [' + TableName + '].('
+ NormalColumns + ')' + CASE WHEN IncludedColumns IS NULL THEN ''
ELSE ' INCLUDE (' + IncludedColumns + ')'
END AS 'CreateScript'
FROM #temp1
-- To generate DROP INDEX SCRIPT
SELECT 'DROP INDEX [' + TableName + '].[' + IndexName + ']' AS 'DropScript'
FROM #temp1
DROP TABLE #temp1
There's a relative complete solution at TechNet.
Adjust the query to your desire:
sys.tables to sys.views
remove default values in select
remove/add some where conditions
This is a bit off topic, but thought I would suggest this anyways:
If you don't want to keep executing your scripts in sql server management studio you can create a runmyscripts.bat file including something like:
#echo off
echo Execute Scripts...
sqlcmd -i C:\Scripts\myscript1.sql
sqlcmd -i C:\Scripts\myscript2.sql
echo Scripts Complete.
echo Press any button to exit.
pause