Retrieve Table Information
The following script can be used to pull the column and index information for a table.
declare @sTableName sysname
-------------------------------------
-- set the table name here
-------------------------------------
set @sTableName = 'PutYourTableNameHere'
declare @lObjectID int
set @lObjectID = object_id(@sTableName)
declare @sTab varchar(5), @sCrlf varchar(5)
set @sTab = char(9)
set @sCrlf = char(13) + char(10)
declare @sTableFields varchar(max) -- hold the fields for the create statement
set @sTableFields = ''
-- declare & open a cursor to iterate thru all of the columns
DECLARE curAllColumns cursor fast_forward for
select [name], iscomputed from syscolumns with (nolock) where [id] = @lObjectID order by colorder
OPEN curAllColumns
-- declare variables to hold the data from our cursor
DECLARE @sColName sysname
, @bIsComputed bit
-- get the 1st row of data from the cursor
FETCH next from curAllColumns into @sColName, @bIsComputed
-- keep going while the last fetch was good
WHILE (@@fetch_status = 0)
begin
set @sTableFields = @sTableFields + @sCrlf + @sTab + ', ' + @sColName
declare @lSysTypeID int
if (@bIsComputed = 0)
begin
-- get the field type- int, varchar, text, etc.
select @sTableFields = @sTableFields + @sTab + b.name
, @lSysTypeID = b.system_type_id
from syscolumns a with (nolock)
inner join (select * from sys.types with (nolock) where [name] <> 'sysname') b on a.xtype = b.system_type_id
where a.[id] = @lObjectID and a.[name] = @sColName
-- get the length and/or precision, if necessary
select @sTableFields = @sTableFields +
case a.xtype
when 173 then '(' + convert(varchar, a.length) + ')' -- binary
when 175 then '(' + convert(varchar, a.length) + ')' -- char
when 106 then '(' + convert(varchar, a.xprec) + ', ' + convert(varchar, a.xscale) + ')' -- decimal
when 239 then '(' + convert(varchar, a.length) + ')' -- nchar
when 108 then '(' + convert(varchar, a.xprec) + ', ' + convert(varchar, a.xscale) + ')' -- numeric
when 231 then '(' +
--convert(varchar, a.length)
case when a.length = -1 then 'max' else convert(varchar, a.length) end
+ ')' -- nchar
when 165 then '(' +
--convert(varchar, a.length)
case when a.length = -1 then 'max' else convert(varchar, a.length) end
+ ')' -- varbinary
when 167 then '(' +
--convert(varchar, a.length)
case when a.length = -1 then 'max' else convert(varchar, a.length) end
+ ')' -- varchar
else ''
end
from syscolumns a with (nolock)
--inner join sys.types b with (nolock) on a.xtype = b.system_type_id
where a.[id] = @lObjectID and a.[name] = @sColName
-- is the column an identity column
select @sTableFields = @sTableFields + ' identity('
+ convert(varchar, c.seed_value)
+ ', '
+ convert(varchar, c.increment_value)
+ ')'
from syscolumns a with (nolock)
inner join sys.identity_columns c with (nolock) on a.id = c.object_id and a.colid = c.column_id
where a.[id] = @lObjectID and a.[name] = @sColName
and c.is_identity = 1
-- is the column nullable?
select @sTableFields = @sTableFields + ' not null'
from syscolumns a with (nolock)
where a.[id] = @lObjectID and a.[name] = @sColName
and a.isnullable = 0
-- set the default, if any
select @sTableFields = @sTableFields + ' default' + d.definition
from syscolumns a with (nolock)
--inner join sys.default_constraints d with (nolock) on a.id = d.parent_object_id
inner join sys.default_constraints d with (nolock) on a.cdefault = d.object_id
where a.[id] = @lObjectID and a.[name] = @sColName
and a.colid = d.parent_column_id
end else begin
-- we have a computed column
select @sTableFields = @sTableFields + ' as ' + b.definition
from syscolumns a with (nolock)
inner join sys.computed_columns b with (nolock) on a.id = b.object_id and a.colid = b.column_id
where a.[id] = @lObjectID and a.[name] = @sColName
end
-- get the next row of data from the cursor
FETCH next from curAllColumns into @sColName, @bIsComputed
end
-- close & deallocate the cursor
CLOSE curAllColumns
DEALLOCATE curAllColumns
-- output the list of columns
print @sTableFields
-- get the primary key index, if any.
if (exists(select 1 from sys.indexes a where a.[object_id] = @lObjectID and a.is_primary_key = 1))
begin
set @sTableFields = ''
select
@sTableFields = @sTableFields +
case
when len(@sTableFields) = 0 then @sCrlf + @sTab + ', primary key ' + ltrim(rtrim(a.type_desc)) + ' (' + c.[name]
else ', ' + c.[name]
end
+
case
when b.is_descending_key = 1 then ' desc' else ''
end
from sys.indexes a
inner join sys.index_columns b on a.[object_id] = b.[object_id] and a.index_id = b.index_id
inner join sys.all_columns c on b.[object_id] = c.[object_id] and b.column_id = c.column_id
where a.[object_id] = @lObjectID and a.is_primary_key = 1
order by b.key_ordinal
set @sTableFields = @sTableFields + ')'
print @sTableFields
end
-- get the unique indexes, if any
if (exists(select 1 from sys.indexes a where a.[object_id] = @lObjectID and a.is_unique_constraint = 1))
begin
set @sTableFields = ''
select
@sTableFields = @sTableFields +
case
when b.key_ordinal = 1 and len(@sTableFields) = 0 then @sCrlf + @sTab + ', unqiue ' + ltrim(rtrim(a.type_desc)) + ' (' + c.[name]
when b.key_ordinal = 1 and len(@sTableFields) > 0 then ')' + @sCrlf + @sTab + ', unqiue ' + ltrim(rtrim(a.type_desc)) + ' (' + c.[name]
else ', ' + c.[name]
end
+
case
when b.is_descending_key = 1 then ' desc' else ''
end
from sys.indexes a
inner join sys.index_columns b on a.[object_id] = b.[object_id] and a.index_id = b.index_id
inner join sys.all_columns c on b.[object_id] = c.[object_id] and b.column_id = c.column_id
where a.[object_id] = @lObjectID and a.is_unique_constraint = 1
order by b.key_ordinal
set @sTableFields = @sTableFields + ')'
print @sTableFields
end
-- get the other indexes, if any
if (exists(select 1 from sys.indexes a where a.[object_id] = @lObjectID and a.is_primary_key = 0 and a.is_unique_constraint = 0))
begin
-- object_name(1474104292)
declare @index_id int = -1
, @idxname varchar(100)
declare @sIdxTemplate varchar(300) = @sCrLf + @sCrLf + 'if exists (select * from dbo.sysindexes where name = N''[INDEXNAME]'' and id = object_id(N''[TABLENAME]''))
drop index [TABLENAME].[INDEXNAME]
GO
'
-- declare & open a cursor
DECLARE curIdx cursor fast_forward for
select a.index_id, a.[name]
from sys.indexes a
where a.[object_id] = @lObjectID and a.is_primary_key = 0 and a.is_unique_constraint = 0
OPEN curIdx
-- get the first row from the cursor
FETCH next from curIdx into @index_id, @idxname
-- keep going while the last fetch was good
while (@@FETCH_STATUS = 0)
begin
set @sTableFields = REPLACE(@sIdxTemplate, 'TABLENAME', OBJECT_NAME(@lObjectID))
select @sTableFields = REPLACE(@sTableFields, 'INDEXNAME', @idxname)
select @sTableFields = @sTableFields + 'CREATE '
+
case
when a.is_unique = 1 then 'UNIQUE '
else ''
end
+
a.type_desc + ' INDEX [' + @idxname + '] ON [' + OBJECT_NAME(@lObjectID) + ']' + @sCrlf + '('
from sys.indexes a
where a.[object_id] = @lObjectID and a.index_id = @index_id
select
@sTableFields = @sTableFields +
case
when b.key_ordinal = 1 then @sCrlf + @sTab + c.[name]
else @sCrlf + @sTab + ', ' + c.[name]
end
+
case
when b.is_descending_key = 1 then ' desc' else ''
end
from sys.indexes a
inner join sys.index_columns b on a.[object_id] = b.[object_id] and a.index_id = b.index_id
inner join sys.all_columns c on b.[object_id] = c.[object_id] and b.column_id = c.column_id
where a.[object_id] = @lObjectID and a.index_id = @index_id
and b.is_included_column = 0
order by a.index_id, b.is_included_column, b.key_ordinal
set @sTableFields = @sTableFields + @sCrlf + ')'
-- add the included columns, if any
if (exists(
select 1
from sys.indexes a
inner join sys.index_columns b on a.[object_id] = b.[object_id] and a.index_id = b.index_id
where a.[object_id] = @lObjectID and a.index_id = @index_id and b.is_included_column = 1))
begin
;with cteA as (
select rownum = ROW_NUMBER() over (order by b.index_column_id)
, c.[name]
, b.is_descending_key
, b.index_column_id
from sys.indexes a
inner join sys.index_columns b on a.[object_id] = b.[object_id] and a.index_id = b.index_id
inner join sys.all_columns c on b.[object_id] = c.[object_id] and b.column_id = c.column_id
where a.[object_id] = @lObjectID and a.index_id = @index_id
and b.is_included_column = 1
)
select
@sTableFields = @sTableFields +
case
when rownum = 1 then @sCrlf + 'INCLUDE (' + a.[name]
else ', ' + a.[name]
end
from cteA a
order by a.index_column_id
set @sTableFields = @sTableFields + ')'
end
-- close the index statement
set @sTableFields = @sTableFields + @sCrlf + 'ON [PRIMARY]' + @sCrlf + 'GO' + @sCrlf
-- send what we have to the output window
print @sTableFields
-- get the next row from the cursor
FETCH next from curIdx into @index_id, @idxname
end
-- close & deallocate the cursor
CLOSE curIdx
DEALLOCATE curIdx
end
Sample output:
, lRowID int identity(1000, 1) not null
, sInfo1 varchar(30) not null
, sInfo2 varchar(44)
, lInfo1 int not null
, lInfo2 int not null
, sLastUser varchar(50) not null default(left(suser_sname(),(50)))
, dtLastMod datetime not null default(getdate())
, sCreatedBy varchar(50) not null default(left(suser_sname(),(50)))
, dtCreateDate datetime not null default(getdate())
, Stamp timestamp not null
, uuid uniqueidentifier not null default(newid())
, primary key NONCLUSTERED (uuid, lRowID)
, unqiue CLUSTERED (lInfo1)
, unqiue NONCLUSTERED (uuid, lInfo2 desc, lRowID)
if exists (select * from dbo.sysindexes where name = N'[IX_TestTable2_1]' and id = object_id(N'[TestTable2]'))
drop index [TestTable2].[IX_TestTable2_1]
GO
CREATE NONCLUSTERED INDEX [IX_TestTable2_1] ON [TestTable2]
(
lInfo1
)
INCLUDE (sInfo1, sInfo2)
ON [PRIMARY]
GO
if exists (select * from dbo.sysindexes where name = N'[IX_TestTable2_2]' and id = object_id(N'[TestTable2]'))
drop index [TestTable2].[IX_TestTable2_2]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_TestTable2_2] ON [TestTable2]
(
dtCreateDate
, lRowID desc
)
INCLUDE (sInfo1, sInfo2)
ON [PRIMARY]
GO
Last modified by Mohit @ 4/5/2025 7:45:55 PM