Select column names and top 1 records along, dynamically - sql

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

Related

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]

Pass table name as parameter

I want to pass the table name as parameter and get all columns size of that table altered by column length + 50.
alter PROCEDURE dbo.testsp
#tablename varchar(100)
AS
BEGIN
DECLARE
#totalWeight TABLE (columnnames nvarchar(100));
INSERT INTO #totalWeight (columnnames)
SELECT name FROM sys.columns
WHERE object_id = object_id(#tablename);
END
GO
This query returns your alteration statements in the last column. You can then run them through dynamic sql.
SELECT
tbl.name 'Table Name',
c.name 'Column Name',
t.name,
c.max_length 'Max Length in Bytes',
c.precision ,
c.scale ,
c.is_nullable,
q1.*,
'alter table ['
+tbl.name
+'] alter column ['
+c.name
+'] '
+t.name
+'('+
convert(nvarchar(1000), CASE WHEN t.name IN ('nchar','nvarchar') THEN c.max_length/2 ELSE c.max_length END +50)
+') '
+ case c.is_nullable when 0 then ' not null' else ' null' end
as 'Alteration statement'
FROM
sys.columns c
INNER JOIN
sys.types t ON c.user_type_id = t.user_type_id
inner join sys.tables tbl on tbl.object_id=c.object_id
CROSS APPLY
(
select
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
+ case c.is_nullable when 0 then ' not null' else ' null' end
as [DDL name before]
)q1
where t.name IN ('char', 'varchar','nchar','nvarchar') and c.max_length>-1
Run the following example of query, it creates a bunch of ALTER statements. Copy-paste the result into a new query window and run it again. Add other data types from sys.types if need.
SELECT 'ALTER TABLE [' + s.name + '].[' + t.name + '] ALTER COLUMN [' +
c.name + '] ' + ty.name + '(' + CAST(c.max_length + 50 AS nvarchar(10)) + ') ' +
CASE WHEN c.is_nullable = 1 THEN 'NULL' ELSE 'NOT NULL' END + ';'
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.types ty ON c.system_type_id = ty.system_type_id
WHERE t.type = 'U' AND
c.system_type_id IN (167 /*varchar*/, 231 /*nvarchar*/)

Easiest Way To Diff Two Table Schemas In SQL Server 2008?

I have to do checks between a development and release database and do this manually, which is both slow and not 100% reliable (I only visually inspect the tables).
Is there a quick and easy way to compare table schemas automatically? Maybe even a feature that does this built right into SQL server?
Edit: I'm comparing structure only, thank you for pointing this out.
I'm a fan of SQL DBDiff, which is an open source tool you can use to compare tables, views, functions, users, etc. of two instances of SQL Server databases and generate a change script between the source and destination databases.
There are some commercial products that do this; Visual Studio 2010 Premium Edition can compare schemas.
Some others:
http://www.red-gate.com/products/SQL_Compare/index.htm
http://www.apexsql.com/sql_tools_diff.aspx
Data or structure or both? Try RedGate sql compare or data compare. They both have free trials and are awesome.
http://www.red-gate.com/products/SQL_Compare/index.htm
http://www.red-gate.com/products/SQL_Data_Compare/index.htm
I'm a little late to the game...but this script I made has worked well for me. It'll work across linked servers too if needed.
use master
go
DECLARE #Server1 VARCHAR(100) ='[CARNYSQLTEST1].'; --include a dot at the end
DECLARE #DB1 VARCHAR(100) = '[ZipCrim]';
DECLARE #Table1 VARCHAR(100) = 'IntAction';
DECLARE #Server2 VARCHAR(100) ='[CARNYSQLDEV].'; --include a dot at the end
DECLARE #DB2 VARCHAR(100) = '[ZipCrim]';
DECLARE #Table2 VARCHAR(100) = 'IntAction';
DECLARE #SQL NVARCHAR(MAX);
SET #SQL =
'
SELECT Table1.ServerName,
Table1.DBName,
Table1.SchemaName,
Table1.TableName,
Table1.ColumnName,
Table1.name DataType,
Table1.Length,
Table1.Precision,
Table1.Scale,
Table1.Is_Identity,
Table1.Is_Nullable,
Table2.ServerName,
Table2.DBName,
Table2.SchemaName,
Table2.TableName,
Table2.ColumnName,
Table2.name DataType,
Table2.Length,
Table2.Precision,
Table2.Scale,
Table2.Is_Identity,
Table2.Is_Nullable
FROM
(SELECT ''' + #Server1 + ''' ServerName,
''' + #DB1 + ''' DbName,
SCHEMA_NAME(t.schema_id) SchemaName,
t.Name TableName,
c.Name ColumnName,
st.Name,
c.Max_Length Length,
c.Precision,
c.Scale,
c.Is_Identity,
c.Is_Nullable
FROM ' + #Server1 + #DB1 + '.sys.tables t
INNER JOIN ' + #Server1 + #DB1 + '.sys.columns c ON t.Object_ID = c.Object_ID
INNER JOIN sys.types st ON St.system_type_id = c.System_Type_id AND st.user_type_id = c.user_type_id
WHERE t.Name = ''' + #Table1 + ''') Table1
FULL OUTER JOIN
(SELECT ''' + #Server2 + ''' ServerName,
''' + #DB2 + ''' DbName,
SCHEMA_NAME(t.schema_id) SchemaName,
t.name TableName,
c.name ColumnName,
st.Name,
c.max_length Length,
c.Precision,
c.Scale,
c.Is_Identity,
c.Is_Nullable
FROM ' + #Server2 + #DB2 + '.sys.tables t
INNER JOIN ' + #Server2 + #DB2 + '.sys.columns c ON t.Object_ID = c.Object_ID
INNER JOIN sys.types st ON St.system_type_id = c.System_Type_id AND st.user_type_id = c.user_type_id
WHERE t.Name = ''' + #Table2 + ''') Table2
ON Table1.ColumnName = Table2.ColumnName
ORDER BY CASE WHEN Table1.ColumnName IS NULL THEN 2 ELSE 1 END, Table1.ColumnName
'
EXEC sp_executesql #SQL
Soo,
Googled this:
for structures:
see also:
My previous answers' links doesn't work anymore for some reason, so here's another answer from TechNet:
DECLARE #Sourcedb sysname
DECLARE #Destdb sysname
DECLARE #Tablename sysname
DECLARE #SQL varchar(max)
SELECT #Sourcedb = '<<SourceDatabaseName>>'
SELECT #Destdb = '<<DestinationDatabaseName>>'
SELECT #Tablename = '<<Tablename>>' -- '%' for all tables
SELECT #SQL = ' SELECT Tablename = ISNULL(Source.tablename,Destination.tablename)
,ColumnName = ISNULL(Source.Columnname,Destination.Columnname)
,Source.Datatype
,Source.Length
,Source.precision
,Destination.Datatype
,Destination.Length
,Destination.precision
,[Column] =
Case
When Source.Columnname IS NULL then ''Column Missing in the Source''
When Destination.Columnname IS NULL then ''Column Missing in the Destination''
ELSE ''''
end
,DataType = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND Source.Datatype <> Destination.Datatype THEN ''Data Type mismatch''
END
,Length = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND Source.Length <> Destination.Length THEN ''Length mismatch''
END
,Precision = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND Source.precision <> Destination.precision THEN ''precision mismatch''
END
,Collation = CASE WHEN Source.Columnname IS NOT NULL
AND Destination.Columnname IS NOT NULL
AND ISNULL(Source.collation_name,'''') <> ISNULL(Destination.collation_name,'''') THEN ''Collation mismatch''
END
FROM
(
SELECT Tablename = so.name
, Columnname = sc.name
, DataType = St.name
, Length = Sc.max_length
, precision = Sc.precision
, collation_name = Sc.collation_name
FROM ' + #Sourcedb + '.SYS.objects So
JOIN ' + #Sourcedb + '.SYS.columns Sc
ON So.object_id = Sc.object_id
JOIN ' + #Sourcedb + '.SYS.types St
ON Sc.system_type_id = St.system_type_id
AND Sc.user_type_id = St.user_type_id
WHERE SO.TYPE =''U''
AND SO.Name like ''' + #Tablename + '''
) Source
FULL OUTER JOIN
(
SELECT Tablename = so.name
, Columnname = sc.name
, DataType = St.name
, Length = Sc.max_length
, precision = Sc.precision
, collation_name = Sc.collation_name
FROM ' + #Destdb + '.SYS.objects So
JOIN ' + #Destdb + '.SYS.columns Sc
ON So.object_id = Sc.object_id
JOIN ' + #Destdb + '.SYS.types St
ON Sc.system_type_id = St.system_type_id
AND Sc.user_type_id = St.user_type_id
WHERE SO.TYPE =''U''
AND SO.Name like ''' + #Tablename + '''
) Destination
ON source.tablename = Destination.Tablename
AND source.Columnname = Destination.Columnname '
EXEC (#Sql)
For a free solution, you can use SQL Server Managements Objects to output the DDL script for each table, view, index, SP, UDF, etc. Then you can compare, either in code, or using a diff tool like WinMerge.
If two tables in same database, you can use this query
select c2.table_name,c2.COLUMN_NAME
from [INFORMATION_SCHEMA].[COLUMNS] c2
where table_name='table1'
and c2.COLUMN_NAME not in (select column_name
from [INFORMATION_SCHEMA].[COLUMNS]
where table_name='table1')
you can take a look at http://cdttools.com/2011/10/sql-diff-erence/ its a low cost alternative, will walk schema between two databases and tell you whats changed. You can then use SQL Mgmt studio to generate "script->As Alter" to build change scripts. (caveat: I wrote it)
Modified a bit of BD.'s query, all credit goes to him. (Changed SCHEMA_NAME(schema_id) to sys.schemas join because SCHEMA_NAME(schema_id) works with current db context which is master, changed sorting and changed column names and added the status column)
USE master
GO
DECLARE
#Server1 VARCHAR(100) = 'Server1.', -- don't forget to include a dot at the end
#Server2 VARCHAR(100) = 'Server2.', -- don't forget to include a dot at the end
#DB1 VARCHAR(100) = 'Database1',
#DB2 VARCHAR(100) = 'Database2'
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = '
SELECT
CASE
WHEN s1.[Column] IS NOT NULL
AND s2.[Column] IS NULL
THEN ''New''
WHEN s1.[Column] IS NULL
AND s2.[Column] IS NOT NULL
THEN ''Deleted''
WHEN s1.[Column] IS NOT NULL
AND s2.[Column] IS NOT NULL
AND (s1.[Type] <> s2.[Type]
OR s1.[Length] <> s2.[Length]
OR s1.[Precision] <> s2.[Precision]
OR s1.Scale <> s2.Scale
OR s1.IsNullable <> s2.IsNullable
OR s1.IsIdentity <> s2.IsIdentity
OR s1.IdentitySeed <> s2.IdentitySeed
OR s1.IdentityIncrement <> s2.IdentityIncrement
OR s1.DefaultValue <> s2.DefaultValue)
THEN ''Changed''
ELSE ''Identical''
END [Status],
s1.[Database],
s1.[Schema],
s1.[Table],
s1.[Column],
s1.[Type],
s1.IsCharType,
s1.[Length],
s1.[Precision],
s1.Scale,
s1.IsNullable,
s1.IsIdentity,
s1.IdentitySeed,
s1.IdentityIncrement,
s1.DefaultValue,
s1.[Order],
s2.[Database],
s2.[Schema],
s2.[Table],
s2.[Column],
s2.[Type],
s2.IsCharType,
s2.[Length],
s2.[Precision],
s2.Scale,
s2.IsNullable,
s2.IsIdentity,
s2.IdentitySeed,
s2.IdentityIncrement,
s2.DefaultValue,
s2.[Order]
FROM (
SELECT
''' + #DB1 + ''' AS [Database],
s.name AS [Schema],
t.name AS [Table],
c.name AS [Column],
tp.name AS [Type],
CASE
WHEN tp.collation_name IS NOT NULL
THEN 1
ELSE 0
END AS IsCharType,
CASE
WHEN c.max_length = -1
THEN ''MAX''
ELSE CAST(c.max_length AS VARCHAR(4))
END AS [Length],
c.[precision],
c.scale,
c.is_nullable AS IsNullable,
c.is_identity AS IsIdentity,
CAST(ISNULL(ic.seed_value, 0) AS INT) AS IdentitySeed,
CAST(ISNULL(ic.increment_value, 0) AS INT) AS IdentityIncrement,
dc.definition AS DefaultValue,
c.column_id AS [Order]
FROM ' + #Server1 + #DB1 + '.sys.tables t
INNER JOIN ' + #Server1 + #DB1 + '.sys.schemas s ON s.schema_id = t.schema_id
INNER JOIN ' + #Server1 + #DB1 + '.sys.columns c ON c.object_id = t.object_id
INNER JOIN ' + #Server1 + #DB1 + '.sys.types tp ON tp.system_type_id = c.system_type_id
LEFT OUTER JOIN ' + #Server1 + #DB1 + '.sys.identity_columns ic ON ic.object_id = t.object_id AND ic.name = c.name
LEFT OUTER JOIN ' + #Server1 + #DB1 + '.sys.default_constraints dc ON dc.object_id = c.default_object_id
) s1
FULL OUTER JOIN (
SELECT
''' + #DB2 + ''' AS [Database],
s.name AS [Schema],
t.name AS [Table],
c.name AS [Column],
tp.name AS [Type],
CASE
WHEN tp.collation_name IS NOT NULL
THEN 1
ELSE 0
END AS IsCharType,
CASE
WHEN c.max_length = -1
THEN ''MAX''
ELSE CAST(c.max_length AS VARCHAR(4))
END AS [Length],
c.[precision],
c.scale,
c.is_nullable AS IsNullable,
c.is_identity AS IsIdentity,
CAST(ISNULL(ic.seed_value, 0) AS INT) AS IdentitySeed,
CAST(ISNULL(ic.increment_value, 0) AS INT) AS IdentityIncrement,
dc.definition AS DefaultValue,
c.column_id AS [Order]
FROM ' + #Server2 + #DB2 + '.sys.tables t
INNER JOIN ' + #Server2 + #DB2 + '.sys.schemas s ON s.schema_id = t.schema_id
INNER JOIN ' + #Server2 + #DB2 + '.sys.columns c ON c.object_id = t.object_id
INNER JOIN ' + #Server2 + #DB2 + '.sys.types tp ON tp.system_type_id = c.system_type_id
LEFT OUTER JOIN ' + #Server2 + #DB2 + '.sys.identity_columns ic ON ic.object_id = t.object_id AND ic.name = c.name
LEFT OUTER JOIN ' + #Server2 + #DB2 + '.sys.default_constraints dc ON dc.object_id = c.default_object_id
) s2
ON s2.[Schema] = s1.[Schema]
AND s2.[Table] = s1.[Table]
AND s2.[Column] = s1.[Column]
ORDER BY
CASE WHEN s1.[Database] IS NULL THEN s2.[Database] ELSE s1.[Database] END,
CASE WHEN s1.[Schema] IS NULL THEN s2.[Schema] ELSE s1.[Schema] END,
CASE WHEN s1.[Table] IS NULL THEN s2.[Table] ELSE s1.[Table] END,
CASE WHEN s1.[Order] IS NULL THEN s2.[Order] ELSE s1.[Order] END
'
EXEC sp_executesql #SQL
You can use the SQL Management studio tools to "Generate scripts" from both databases. Then use your favorite text comparison tool to see any differences.
In the old days, this worked great, but in SQL 2005 the generate script code changed and the objects were no longer created in the same order, so the text comparison is less useful. I have not tested this in more recent versions of SQL so it may have been fixed. You can also try http://exportsqlscript.codeplex.com/ which I have used with good success to output the DDL as scripts for source code control and comparing versions.
References:
https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=332400&wa=wsignin1.0
http://social.msdn.microsoft.com/Forums/en-US/sqltools/thread/505fd238-e0dc-42ae-8a54-2dceace81bb3/
http://exportsqlscript.codeplex.com/

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