Skip to content

Instantly share code, notes, and snippets.

@asw456
Forked from jjradha/procedure sp_GetTableDef
Last active March 7, 2022 19:45
Show Gist options
  • Save asw456/b1fd41dade3124c8b76e03e11d92c315 to your computer and use it in GitHub Desktop.
Save asw456/b1fd41dade3124c8b76e03e11d92c315 to your computer and use it in GitHub Desktop.
PRINT 'THE SERVER IS ' + @@SERVERNAME
--select db_name()
PRINT 'THE DATABASE IS ' + db_NAME()
PRINT ''
GO
USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--SELECT @@SERVERNAME
PRINT 'THE SERVER IS ' + @@SERVERNAME
--select db_name()
PRINT 'THE DATABASE IS ' + db_NAME()
PRINT ''
GO
USE MASTER
GO
GO
BEGIN TRY
PRINT @@SERVERNAME
PRINT DB_NAME()
PRINT 'PROCEDURE sp_GetTableDef'
DROP PROCEDURE sp_GetTableDef
print 'dropped PROCEDURE sp_GetTableDef'
END TRY
BEGIN CATCH
END CATCH
GO
-- USAGE: exec sp_GetTableDef GMACT
-- or exec sp_GetTableDef 'bob.example'
-- or exec sp_GetTableDef '[schemaname].[tablename]'
-- or exec sp_GetTableDef #temp
--#################################################################################################
-- copyright 2004-2013 by Lowell Izaguirre scripts*at*stormrage.com all rights reserved.
-- http://www.stormrage.com/SQLStuff/sp_GetDDL_Latest.txt
--Purpose: Script Any Table, Temp Table or Object
--
-- see the thread here for lots of details: http://www.sqlservercentral.com/Forums/Topic751783-566-7.aspx
-- You can use this however you like...this script is not rocket science, but it took a bit of work to create.
-- the only thing that I ask
-- is that if you adapt my procedure or make it better, to simply send me a copy of it,
-- so I can learn from the things you've enhanced.The feedback you give will be what makes
-- it worthwhile to me, and will be fed back to the SQL community.
-- add this to your toolbox of helpful scripts.
--#################################################################################################
--
-- V300 uses String concatination and sys.tables instead of a cursor
-- V301 enhanced 07/31/2009 to include extended properties definitions
-- V302 fixes an issue where the schema is created , ie 'bob', but no user named 'bob' owns the schema, so the table is not found
-- V303 fixes an issue where all rules are appearing, instead of jsut the rule related to a column
-- V304 testing whether vbCrLf is better than just CHAR(13), some formatting cleanup with GO statements
-- also fixed an issue with the conversion from syscolumns to sys.columns, max-length is only field we need, not [precision]
-- V305 user feedback helped me find that the type_name function should call user_type_id instead of system_type_id
-- also fixed issue where identity definition missing from numeric/decimal definition
-- V306 fixes the computed columns definition that got broken/removed somehow in V300
-- also formatting when decimal is not an identity
-- V307 fixes bug identified by David Griffiths-491597 from SSC where the @TABLE_ID
-- is reselected, but without it's schema , potentially selecting the wrong table
-- also fixed is the missing size definition for varbinary, also found by David Griffith
-- V308 abtracted all SQLs to use Table Alaises
-- added logic to script a temp table.
-- added warning about possibly not being marked as system object.
-- V309 added logic based on feedback from Vincent Wylenzek @SSC to return the definition from sys.sql_modules for
-- any object like procedure/view/function/trigger, and not just a table.
-- note previously, if you pointed sp_GetTableDef at a view, it returned the view definition as a table...
-- now it will return the view definition instead.
-- V309a returns multi row recordset, one line per record
-- V310a fixed the commented out code related to collation identified by moadh.bs @SSC
-- changed the DEFAULT definitions to not include the default name.
-- V310b Added PERSISTED to calculated columns where applicable
-- V310b fixed COLLATE statement for temp tables
-- V310c fixed NVARCHAR size misreported as doubled.
-- V311 fixed issue where indexes did not identify if the column was ASC or DESC found by nikus @ SSC
-- V311a fixed issue where indexes did not identify if the index was CLUSTERED or NONCLUSTERED found by nikus @ SSC 02/22/2013
-- V312 got rid of all upper casing, and allowing all scripts to generate the exact object names in cases of case sensitive databases.
-- now using the case sensitive name of the table passed: so of you did 'exec sp_GetTableDef invoicedocs , it might return the script for InvoiceDocs, as that is how it is spelled in sys.objects.
-- added if exists(drop table/procedure/function) statement to the scripting automatically.
-- toggled the commented out code to list any default constraints by name, hopefully to be more accurate..
-- formatting of index statements to be multi line for better readability
--V314 03/30/2015
-- did i mention this scripts out temp tables too? sp_GetTableDef #tmp
-- scripts any object:table,#temptable procedure, function, view or trigger
-- added ability to script synonyms
-- moved logic for REAL datatype to fix error when scripting real columns
-- added OmaCoders suggestion to script column extended properties as well.
-- added matt_slack suggestion to script schemaname as part of index portion of script.
-- minor script cleanup to use QUOTENAME insead of concatenating square brackets.
-- changed compatibility to 2008 and above only, now filtered idnexes with WHERE statmeents script correctly
-- foreign key tables and columns in script now quotenamed to accoutn for spaces in names; previously an error for Applciation ID instead of [Application ID]
-- DROP PROCEDURE [dbo].[sp_GetTableDef]
--#############################################################################
--if you are going to put this in MASTER, and want it to be able to query
--each database's sys.indexes, you MUST mark it as a system procedure:
--EXECUTE sp_ms_marksystemobject 'sp_GetTableDef'
--#############################################################################
CREATE PROCEDURE [dbo].[sp_GetTableDef]
@TBL VARCHAR(255)
AS
BEGIN
SET NOCOUNT ON
DECLARE @TBLNAME VARCHAR(200),
@SCHEMANAME VARCHAR(255),
@STRINGLEN INT,
@TABLE_ID INT,
@FINALSQL VARCHAR(MAX),
@CONSTRAINTSQLS VARCHAR(MAX),
@CHECKCONSTSQLS VARCHAR(MAX),
@RULESCONSTSQLS VARCHAR(MAX),
@FKSQLS VARCHAR(MAX),
@TRIGGERSTATEMENT VARCHAR(MAX),
@EXTENDEDPROPERTIES VARCHAR(MAX),
@INDEXSQLS VARCHAR(MAX),
@vbCrLf CHAR(2),
@ISSYSTEMOBJECT INT,
@PROCNAME VARCHAR(256),
@input VARCHAR(MAX),
@ObjectTypeFound VARCHAR(255)
--##############################################################################
-- INITIALIZE
--##############################################################################
SET @input = ''
--new code: determine whether this proc is marked as a system proc with sp_ms_marksystemobject,
--which flips the is_ms_shipped bit in sys.objects
SELECT @ISSYSTEMOBJECT = ISNULL(is_ms_shipped,0),@PROCNAME = ISNULL(name,'sp_GetDDL') FROM sys.objects WHERE OBJECT_ID = @@PROCID
IF @ISSYSTEMOBJECT IS NULL
SELECT @ISSYSTEMOBJECT = ISNULL(is_ms_shipped,0),@PROCNAME = ISNULL(name,'pp_GetDDL') FROM master.sys.objects WHERE OBJECT_ID = @@PROCID
IF @ISSYSTEMOBJECT IS NULL
SET @ISSYSTEMOBJECT = 0
IF @PROCNAME IS NULL
SET @PROCNAME = 'sp_GetTableDef'
--SET @TBL = '[DBO].[WHATEVER1]'
--does the tablename contain a schema?
SET @vbCrLf = CHAR(13) + CHAR(10)
SELECT @SCHEMANAME = ISNULL(PARSENAME(@TBL,2),'dbo') ,
@TBLNAME = PARSENAME(@TBL,1)
SELECT
@TBLNAME = [name],
@TABLE_ID = [OBJECT_ID]
FROM sys.objects OBJS
WHERE [TYPE] IN ('S','U')
AND [name] <> 'dtproperties'
AND [name] = @TBLNAME
AND [SCHEMA_ID] = SCHEMA_ID(@SCHEMANAME) ;
--##############################################################################
-- Check If TEMP TableName is Valid
--##############################################################################
IF LEFT(@TBLNAME,1) = '#'
BEGIN
PRINT '--TEMP TABLE ' + quotename(@TBLNAME) + ' FOUND'
IF OBJECT_ID('tempdb..' + quotename(@TBLNAME)) IS NOT NULL
BEGIN
PRINT '--GOIN TO TEMP PROCESSING'
GOTO TEMPPROCESS
END
END
ELSE
BEGIN
PRINT '--Non-Temp Table, ' + quotename(@TBLNAME) + ' continue Processing'
END
--##############################################################################
-- Check If TableName is Valid
--##############################################################################
IF ISNULL(@TABLE_ID,0) = 0
BEGIN
--V309 code: see if it is an object and not a table.
SELECT
@TBLNAME = [name],
@TABLE_ID = [OBJECT_ID],
@ObjectTypeFound = type_desc
FROM sys.objects OBJS
--WHERE [type_desc] IN('SQL_STORED_PROCEDURE','VIEW','SQL_TRIGGER','AGGREGATE_FUNCTION','SQL_INLINE_TABLE_VALUED_FUNCTION','SQL_TABLE_VALUED_FUNCTION','SQL_SCALAR_FUNCTION','SYNONYMN')
WHERE [TYPE] IN ('P','V','TR','AF','IF','FN','TF','SN')
AND [name] <> 'dtproperties'
AND [name] = @TBLNAME
AND [SCHEMA_ID] = SCHEMA_ID(@SCHEMANAME) ;
IF ISNULL(@TABLE_ID,0) <> 0
BEGIN
--adding a drop statement.
IF @ObjectTypeFound = 'SYNONYM'
BEGIN
SELECT @FINALSQL =
'IF EXISTS(SELECT * FROM sys.synonyms WHERE name = '''
+ name
+ ''''
+ ' AND base_object_name <> ''' + base_object_name + ''')'
+ @vbCrLf
+ ' DROP SYNONYM ' + quotename(name) + ''
+ @vbCrLf
+'GO'
+ @vbCrLf
+'IF NOT EXISTS(SELECT * FROM sys.synonyms WHERE name = '''
+ name
+ ''')'
+ @vbCrLf
+ 'CREATE SYNONYM ' + quotename(name) + ' FOR ' + base_object_name +';'
from sys.synonyms
WHERE [name] = @TBLNAME
AND [SCHEMA_ID] = SCHEMA_ID(@SCHEMANAME);
END
ELSE
BEGIN
SELECT @FINALSQL =
'IF OBJECT_ID(''' + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ''') IS NOT NULL ' + @vbcrlf
+ 'DROP ' + CASE
WHEN OBJS.[type] IN ('P')
THEN ' PROCEDURE '
WHEN OBJS.[type] IN ('V')
THEN ' VIEW '
WHEN OBJS.[type] IN ('TR')
THEN ' TRIGGER '
ELSE ' FUNCTION '
END
+ QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ' ' + @vbcrlf + 'GO' + @vbcrlf
+ def.definition
FROM sys.objects OBJS
INNER JOIN sys.sql_modules def
ON OBJS.object_id = def.object_id
WHERE OBJS.[type] IN ('P','V','TR','AF','IF','FN','TF')
AND OBJS.[name] <> 'dtproperties'
AND OBJS.[name] = @TBLNAME
AND OBJS.[schema_id] = SCHEMA_ID(@SCHEMANAME) ;
END
SET @input = @FINALSQL
--ten years worth of days from todays date:
;WITH E01(N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1), -- 10 or 10E01 rows
E02(N) AS (SELECT 1 FROM E01 a, E01 b), -- 100 or 10E02 rows
E04(N) AS (SELECT 1 FROM E02 a, E02 b), -- 10,000 or 10E04 rows
E08(N) AS (SELECT 1 FROM E04 a, E04 b), --100,000,000 or 10E08 rows
--E16(N) AS (SELECT 1 FROM E08 a, E08 b), --10E16 or more rows than you'll EVER need,
Tally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E08),
ItemSplit(
ItemOrder,
Item
) AS (
SELECT N,
SUBSTRING(@vbCrLf + @input + @vbCrLf,N + DATALENGTH(@vbCrLf),CHARINDEX(@vbCrLf,@vbCrLf + @input + @vbCrLf,N + DATALENGTH(@vbCrLf)) - N - DATALENGTH(@vbCrLf))
FROM Tally
WHERE N < DATALENGTH(@vbCrLf + @input)
--WHERE N < DATALENGTH(@vbCrLf + @input) -- REMOVED added @vbCrLf
AND SUBSTRING(@vbCrLf + @input + @vbCrLf,N,DATALENGTH(@vbCrLf)) = @vbCrLf --Notice how we find the delimiter
)
SELECT
--row_number() over (order by ItemOrder) as ItemID,
Item
FROM ItemSplit;
RETURN 0
END
ELSE
BEGIN
SET @FINALSQL = 'Object ' + quotename(@SCHEMANAME) + '.' + quotename(@TBLNAME) + ' does not exist in Database ' + quotename(DB_NAME()) + ' '
--+ CASE
-- WHEN @ISSYSTEMOBJECT = 0 THEN @vbCrLf + ' (also note that ' + @PROCNAME + ' is not marked as a system proc and cross db access to sys.tables will fail.)'
-- ELSE ''
-- END
IF LEFT(@TBLNAME,1) = '#'
SET @FINALSQL = @FINALSQL + ' OR in The tempdb database.'
SELECT @FINALSQL AS Item;
RETURN 0
END
END
--##############################################################################
-- Valid Table, Continue Processing
--##############################################################################
SELECT
@FINALSQL = 'IF OBJECT_ID(''' + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ''') IS NOT NULL ' + @vbcrlf
+ 'DROP TABLE ' + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ' ' + @vbcrlf + 'GO' + @vbcrlf
+ 'CREATE TABLE ' + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ' ( '
--removed invalid code here which potentially selected wrong table--thanks David Grifiths @SSC!
SELECT
@STRINGLEN = MAX(LEN(COLS.[name])) + 1
FROM sys.objects OBJS
INNER JOIN sys.columns COLS
ON OBJS.[object_id] = COLS.[object_id]
AND OBJS.[object_id] = @TABLE_ID;
--##############################################################################
--Get the columns, their definitions and defaults.
--##############################################################################
SELECT
@FINALSQL = @FINALSQL
+ CASE
WHEN COLS.[is_computed] = 1
THEN @vbCrLf
+ QUOTENAME(COLS.[name])
+ ' '
+ SPACE(@STRINGLEN - LEN(COLS.[name]))
+ 'AS ' + ISNULL(CALC.definition,'')
+ CASE
WHEN CALC.is_persisted = 1
THEN ' PERSISTED'
ELSE ''
END
ELSE @vbCrLf
+ QUOTENAME(COLS.[name])
+ ' '
+ SPACE(@STRINGLEN - LEN(COLS.[name]))
+ UPPER(TYPE_NAME(COLS.[user_type_id]))
+ CASE
--IE NUMERIC(10,2)
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('decimal','numeric')
THEN '('
+ CONVERT(VARCHAR,COLS.[precision])
+ ','
+ CONVERT(VARCHAR,COLS.[scale])
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[precision])
+ ','
+ CONVERT(VARCHAR,COLS.[scale])))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLUMNPROPERTY ( @TABLE_ID , COLS.[name] , 'IsIdentity' ) = 0
THEN ''
ELSE ' IDENTITY('
+ CONVERT(VARCHAR,ISNULL(IDENT_SEED(@TBLNAME),1) )
+ ','
+ CONVERT(VARCHAR,ISNULL(IDENT_INCR(@TBLNAME),1) )
+ ')'
END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
--IE FLOAT(53)
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('float') --,'real')
THEN
--addition: if 53, no need to specifically say (53), otherwise display it
CASE
WHEN COLS.[precision] = 53
THEN SPACE(11 - LEN(CONVERT(VARCHAR,COLS.[precision])))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,COLS.[precision])
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[precision])))
+ SPACE(7) + SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--ie VARCHAR(40)
--##############################################################################
-- COLLATE STATEMENTS
-- personally i do not like collation statements,
-- but included here to make it easy on those who do
--##############################################################################
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('char','varchar')
THEN CASE
WHEN COLS.[max_length] = -1
THEN '(max)'
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[max_length])))
+ SPACE(7) + SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
----collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,COLS.[max_length])
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[max_length])))
+ SPACE(7) + SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
----collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--ie NVARCHAR(40)
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('nchar','nvarchar')
THEN CASE
WHEN COLS.[max_length] = -1
THEN '(max)'
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length] / 2))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
----collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,(COLS.[max_length] / 2))
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length] / 2))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
----collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--ie datetime
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('datetime','money','text','image','real')
THEN SPACE(18 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ ' '
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
--IE VARBINARY(500)
WHEN TYPE_NAME(COLS.[user_type_id]) = 'varbinary'
THEN
CASE
WHEN COLS.[max_length] = -1
THEN '(max)'
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length]))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,(COLS.[max_length]))
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length]))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--IE INT
ELSE SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLUMNPROPERTY ( @TABLE_ID , COLS.[name] , 'IsIdentity' ) = 0
THEN ' '
ELSE ' IDENTITY('
+ CONVERT(VARCHAR,ISNULL(IDENT_SEED(@TBLNAME),1) )
+ ','
+ CONVERT(VARCHAR,ISNULL(IDENT_INCR(@TBLNAME),1) )
+ ')'
END
+ SPACE(2)
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
+ CASE
WHEN COLS.[default_object_id] = 0
THEN ''
--ELSE ' DEFAULT ' + ISNULL(def.[definition] ,'')
--optional section in case NAMED default constraints are needed:
ELSE ' CONSTRAINT ' + quotename(def.name) + ' DEFAULT ' + ISNULL(def.[definition] ,'')
--i thought it needed to be handled differently! NOT!
END --CASE cdefault
END --iscomputed
+ ','
FROM sys.columns COLS
LEFT OUTER JOIN sys.default_constraints DEF
ON COLS.[default_object_id] = DEF.[object_id]
LEFT OUTER JOIN sys.computed_columns CALC
ON COLS.[object_id] = CALC.[object_id]
AND COLS.[column_id] = CALC.[column_id]
WHERE COLS.[object_id]=@TABLE_ID
ORDER BY COLS.[column_id]
--##############################################################################
--used for formatting the rest of the constraints:
--##############################################################################
SELECT
@STRINGLEN = MAX(LEN([name])) + 1
FROM sys.objects OBJS
--##############################################################################
--PK/Unique Constraints and Indexes, using the 2005/08 INCLUDE syntax
--##############################################################################
DECLARE @Results TABLE (
[SCHEMA_ID] INT,
[SCHEMA_NAME] VARCHAR(255),
[OBJECT_ID] INT,
[OBJECT_NAME] VARCHAR(255),
[index_id] INT,
[index_name] VARCHAR(255),
[ROWS] BIGINT,
[SizeMB] DECIMAL(19,3),
[IndexDepth] INT,
[TYPE] INT,
[type_desc] VARCHAR(30),
[fill_factor] INT,
[is_unique] INT,
[is_primary_key] INT ,
[is_unique_constraint] INT,
[index_columns_key] VARCHAR(MAX),
[index_columns_include] VARCHAR(MAX)
--[has_filter] bit ,
--[filter_definition] VARCHAR(MAX)
)
INSERT INTO @Results
SELECT
SCH.schema_id, SCH.[name] AS SCHEMA_NAME,
OBJS.[object_id], OBJS.[name] AS OBJECT_NAME,
IDX.index_id, ISNULL(IDX.[name], '---') AS index_name,
partitions.Rows, partitions.SizeMB, INDEXPROPERTY(OBJS.[object_id], IDX.[name], 'IndexDepth') AS IndexDepth,
IDX.type, IDX.type_desc, IDX.fill_factor,
IDX.is_unique, IDX.is_primary_key, IDX.is_unique_constraint,
ISNULL(Index_Columns.index_columns_key, '---') AS index_columns_key,
ISNULL(Index_Columns.index_columns_include, '---') AS index_columns_include
--IDX.[has_filter],
--IDX.[filter_definition]
FROM sys.objects OBJS
INNER JOIN sys.schemas SCH ON OBJS.schema_id=SCH.schema_id
INNER JOIN sys.indexes IDX ON OBJS.[object_id]=IDX.[object_id]
INNER JOIN (
SELECT
[OBJECT_ID], index_id, SUM(row_count) AS ROWS,
CONVERT(NUMERIC(19,3), CONVERT(NUMERIC(19,3), SUM(in_row_reserved_page_count+lob_reserved_page_count+row_overflow_reserved_page_count))/CONVERT(NUMERIC(19,3), 128)) AS SizeMB
FROM sys.dm_db_partition_stats STATS
GROUP BY [OBJECT_ID], index_id
) AS partitions
ON IDX.[object_id]=partitions.[object_id]
AND IDX.index_id=partitions.index_id
CROSS APPLY (
SELECT
LEFT(index_columns_key, LEN(index_columns_key)-1) AS index_columns_key,
LEFT(index_columns_include, LEN(index_columns_include)-1) AS index_columns_include
FROM
(
SELECT
(
SELECT QUOTENAME(COLS.[name]) + CASE WHEN IXCOLS.is_descending_key = 0 THEN ' asc' ELSE ' desc' END + ',' + ' '
FROM sys.index_columns IXCOLS
INNER JOIN sys.columns COLS
ON IXCOLS.column_id = COLS.column_id
AND IXCOLS.[object_id] = COLS.[object_id]
WHERE IXCOLS.is_included_column = 0
AND IDX.[object_id] = IXCOLS.[object_id]
AND IDX.index_id = IXCOLS.index_id
ORDER BY key_ordinal
FOR XML PATH('')
) AS index_columns_key,
(
SELECT QUOTENAME(COLS.[name]) + ',' + ' '
FROM sys.index_columns IXCOLS
INNER JOIN sys.columns COLS
ON IXCOLS.column_id = COLS.column_id
AND IXCOLS.[object_id] = COLS.[object_id]
WHERE IXCOLS.is_included_column = 1
AND IDX.[object_id] = IXCOLS.[object_id]
AND IDX.index_id = IXCOLS.index_id
ORDER BY index_column_id
FOR XML PATH('')
) AS index_columns_include
) AS Index_Columns
) AS Index_Columns
WHERE SCH.[name] LIKE CASE
WHEN @SCHEMANAME = ''
THEN SCH.[name]
ELSE @SCHEMANAME
END
AND OBJS.[name] LIKE CASE
WHEN @TBLNAME = ''
THEN OBJS.[name]
ELSE @TBLNAME
END
ORDER BY
SCH.[name],
OBJS.[name],
IDX.[name]
--@Results table has both PK,s Uniques and indexes in thme...pull them out for adding to funal results:
SET @CONSTRAINTSQLS = ''
SET @INDEXSQLS = ''
--##############################################################################
--constriants
--##############################################################################
SELECT @CONSTRAINTSQLS = @CONSTRAINTSQLS
+ CASE
WHEN is_primary_key = 1 OR is_unique = 1
THEN @vbCrLf
+ 'CONSTRAINT ' + quotename(index_name) + ' '
+ CASE
WHEN is_primary_key = 1
THEN ' PRIMARY KEY '
ELSE CASE
WHEN is_unique = 1
THEN ' UNIQUE '
ELSE ''
END
END
+ type_desc
+ CASE
WHEN type_desc='NONCLUSTERED'
THEN ''
ELSE ' '
END
+ ' (' + index_columns_key + ')'
+ CASE
WHEN index_columns_include <> '---'
THEN ' INCLUDE (' + index_columns_include + ')'
ELSE ''
END
+ CASE
WHEN fill_factor <> 0
THEN ' WITH FILLFACTOR = ' + CONVERT(VARCHAR(30),fill_factor)
ELSE ''
END
ELSE ''
END + ','
FROM @RESULTS
WHERE [type_desc] != 'HEAP'
AND is_primary_key = 1
OR is_unique = 1
ORDER BY
is_primary_key DESC,
is_unique DESC
--##############################################################################
--indexes
--##############################################################################
SELECT @INDEXSQLS = @INDEXSQLS
+ CASE
WHEN is_primary_key = 0 OR is_unique = 0
THEN @vbCrLf
+ 'CREATE ' + type_desc + ' INDEX ' + quotename(index_name) + ' '
+ @vbCrLf
+ ' ON ' + quotename([schema_name]) + '.' + quotename([OBJECT_NAME])
+ ' (' + index_columns_key + ')'
+ CASE
WHEN index_columns_include <> '---'
THEN @vbCrLf + ' INCLUDE (' + index_columns_include + ')'
ELSE ''
END
--2008 filtered indexes syntax
--+ CASE
-- WHEN has_filter = 1
-- THEN @vbCrLf + ' WHERE ' + filter_definition
-- ELSE ''
-- END
+ CASE
WHEN fill_factor <> 0
THEN @vbCrLf + ' WITH FILLFACTOR = ' + CONVERT(VARCHAR(30),fill_factor)
ELSE ''
END
END
FROM @RESULTS
WHERE [type_desc] != 'HEAP'
AND is_primary_key = 0
AND is_unique = 0
ORDER BY
is_primary_key DESC,
is_unique DESC
IF @INDEXSQLS <> ''
SET @INDEXSQLS = @vbCrLf + 'GO' + @vbCrLf + @INDEXSQLS
--##############################################################################
--CHECK Constraints
--##############################################################################
SET @CHECKCONSTSQLS = ''
SELECT
@CHECKCONSTSQLS = @CHECKCONSTSQLS
+ @vbCrLf
+ ISNULL('CONSTRAINT ' + quotename(OBJS.[name]) + ' '
+ SPACE(@STRINGLEN - LEN(OBJS.[name]))
+ ' CHECK ' + ISNULL(CHECKS.definition,'')
+ ',','')
FROM sys.objects OBJS
INNER JOIN sys.check_constraints CHECKS ON OBJS.[object_id] = CHECKS.[object_id]
WHERE OBJS.type = 'C'
AND OBJS.parent_object_id = @TABLE_ID
--##############################################################################
--FOREIGN KEYS
--##############################################################################
SET @FKSQLS = '' ;
SELECT
@FKSQLS=@FKSQLS
+ @vbCrLf
+ 'CONSTRAINT ' + quotename(OBJECT_NAME(constid)) + ''
+ SPACE(@STRINGLEN - LEN(OBJECT_NAME(constid) ))
+ ' FOREIGN KEY (' + quotename(COL_NAME(fkeyid,fkey))
+ ') REFERENCES ' + quotename(OBJECT_NAME(rkeyid))
+'(' + quotename(COL_NAME(rkeyid,rkey)) + '),'
FROM sysforeignkeys FKEYS
WHERE fkeyid = @TABLE_ID
--##############################################################################
--RULES
--##############################################################################
SET @RULESCONSTSQLS = ''
SELECT
@RULESCONSTSQLS = @RULESCONSTSQLS
+ ISNULL(
@vbCrLf
+ 'if not exists(SELECT [name] FROM sys.objects WHERE TYPE=''R'' AND schema_id = ' + CONVERT(VARCHAR(30),OBJS.schema_id) + ' AND [name] = ''' + quotename(OBJECT_NAME(COLS.[rule_object_id])) + ''')' + @vbCrLf
+ MODS.definition + @vbCrLf + 'GO' + @vbCrLf
+ 'EXEC sp_binderule ' + quotename(OBJS.[name]) + ', ''' + quotename(OBJECT_NAME(COLS.[object_id])) + '.' + quotename(COLS.[name]) + '''' + @vbCrLf + 'GO' ,'')
FROM sys.columns COLS
INNER JOIN sys.objects OBJS
ON OBJS.[object_id] = COLS.[object_id]
INNER JOIN sys.sql_modules MODS
ON COLS.[rule_object_id] = MODS.[object_id]
WHERE COLS.[rule_object_id] <> 0
AND COLS.[object_id] = @TABLE_ID
--##############################################################################
--TRIGGERS
--##############################################################################
SET @TRIGGERSTATEMENT = ''
SELECT
@TRIGGERSTATEMENT = @TRIGGERSTATEMENT + @vbCrLf + MODS.[definition] + @vbCrLf + 'GO'
FROM sys.sql_modules MODS
WHERE [OBJECT_ID] IN(SELECT
[OBJECT_ID]
FROM sys.objects OBJS
WHERE TYPE = 'TR'
AND [parent_object_id] = @TABLE_ID)
IF @TRIGGERSTATEMENT <> ''
SET @TRIGGERSTATEMENT = @vbCrLf + 'GO' + @vbCrLf + @TRIGGERSTATEMENT
--##############################################################################
--NEW SECTION QUERY ALL EXTENDED PROPERTIES
--##############################################################################
SET @EXTENDEDPROPERTIES = ''
SELECT @EXTENDEDPROPERTIES =
@EXTENDEDPROPERTIES + @vbCrLf +
'EXEC sys.sp_addextendedproperty
@name = N''' + [name] + ''', @value = N''' + REPLACE(CONVERT(VARCHAR(MAX),[VALUE]),'''','''''') + ''',
@level0type = N''SCHEMA'', @level0name = ' + quotename(@SCHEMANAME) + ',
@level1type = N''TABLE'', @level1name = ' + quotename(@TBLNAME) + ';'
--SELECT objtype, objname, name, value
FROM fn_listextendedproperty (NULL, 'schema', @SCHEMANAME, 'table', @TBLNAME, NULL, NULL);
--OMacoder suggestion for column extended properties http://www.sqlservercentral.com/Forums/FindPost1651606.aspx
SELECT @EXTENDEDPROPERTIES =
@EXTENDEDPROPERTIES + @vbCrLf +
'EXEC sys.sp_addextendedproperty
@name = N''' + [name] + ''', @value = N''' + REPLACE(convert(varchar(max),[value]),'''','''''') + ''',
@level0type = N''SCHEMA'', @level0name = ' + quotename(@SCHEMANAME) + ',
@level1type = N''TABLE'', @level1name = ' + quotename(@TBLNAME) + ',
@level2type = N''COLUMN'', @level2name = ' + quotename([objname]) + ';'
--SELECT objtype, objname, name, value
FROM fn_listextendedproperty (NULL, 'schema', @SCHEMANAME, 'table', @TBLNAME, 'column', NULL)
IF @EXTENDEDPROPERTIES <> ''
SET @EXTENDEDPROPERTIES = @vbCrLf + 'GO' + @vbCrLf + @EXTENDEDPROPERTIES
--##############################################################################
--FINAL CLEANUP AND PRESENTATION
--##############################################################################
--at this point, there is a trailing comma, or it blank
SELECT
@FINALSQL = @FINALSQL
+ @CONSTRAINTSQLS
+ @CHECKCONSTSQLS
+ @FKSQLS
--note that this trims the trailing comma from the end of the statements
SET @FINALSQL = SUBSTRING(@FINALSQL,1,LEN(@FINALSQL) -1) ;
SET @FINALSQL = @FINALSQL + ')' + @vbCrLf ;
SET @input = @vbCrLf
+ @FINALSQL
+ @INDEXSQLS
+ @RULESCONSTSQLS
+ @TRIGGERSTATEMENT
+ @EXTENDEDPROPERTIES
--ten years worth of days from todays date:
;WITH E01(N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1), -- 10 or 10E01 rows
E02(N) AS (SELECT 1 FROM E01 a, E01 b), -- 100 or 10E02 rows
E04(N) AS (SELECT 1 FROM E02 a, E02 b), -- 10,000 or 10E04 rows
E08(N) AS (SELECT 1 FROM E04 a, E04 b), --100,000,000 or 10E08 rows
--E16(N) AS (SELECT 1 FROM E08 a, E08 b), --10E16 or more rows than you'll EVER need,
Tally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E08),
ItemSplit(
ItemOrder,
Item
) AS (
SELECT N,
SUBSTRING(@vbCrLf + @input + @vbCrLf,N + DATALENGTH(@vbCrLf),CHARINDEX(@vbCrLf,@vbCrLf + @input + @vbCrLf,N + DATALENGTH(@vbCrLf)) - N - DATALENGTH(@vbCrLf))
FROM Tally
WHERE N < DATALENGTH(@vbCrLf + @input)
--WHERE N < DATALENGTH(@vbCrLf + @input) -- REMOVED added @vbCrLf
AND SUBSTRING(@vbCrLf + @input + @vbCrLf,N,DATALENGTH(@vbCrLf)) = @vbCrLf --Notice how we find the delimiter
)
SELECT
--row_number() over (order by ItemOrder) as ItemID,
Item
FROM ItemSplit
RETURN;
--##############################################################################
-- END Normal Table Processing
--##############################################################################
--simple, primitive version to get the results of a TEMP table from the TEMP db.
--##############################################################################
-- NEW Temp Table Logic
--##############################################################################
TEMPPROCESS:
SELECT @TABLE_ID = OBJECT_ID('tempdb..' + @TBLNAME)
--##############################################################################
-- Valid temp Table, Continue Processing
--##############################################################################
SELECT
@FINALSQL = 'IF OBJECT_ID(''tempdb.' + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ''') IS NOT NULL ' + @vbcrlf
+ 'DROP TABLE ' + QUOTENAME(@SCHEMANAME) + '.' + QUOTENAME(@TBLNAME) + ' ' + @vbcrlf + 'GO' + @vbcrlf
+ 'CREATE TABLE ' + quotename(@SCHEMANAME) + '.' + quotename(@TBLNAME) + ' ( '
--removed invalud cide here which potentially selected wrong table--thansk David Grifiths @SSC!
SELECT
@STRINGLEN = MAX(LEN(COLS.[name])) + 1
FROM tempdb.sys.objects OBJS
INNER JOIN tempdb.sys.columns COLS
ON OBJS.[object_id] = COLS.[object_id]
AND OBJS.[object_id] = @TABLE_ID;
--##############################################################################
--Get the columns, their definitions and defaults.
--##############################################################################
SELECT
@FINALSQL = @FINALSQL
+ CASE
WHEN COLS.[is_computed] = 1
THEN @vbCrLf
+ QUOTENAME(COLS.[name])
+ ' '
+ SPACE(@STRINGLEN - LEN(COLS.[name]))
+ 'AS ' + ISNULL(CALC.definition,'')
+ CASE
WHEN CALC.is_persisted = 1
THEN ' PERSISTED'
ELSE ''
END
ELSE @vbCrLf
+ QUOTENAME(COLS.[name])
+ ' '
+ SPACE(@STRINGLEN - LEN(COLS.[name]))
+ UPPER(TYPE_NAME(COLS.[user_type_id]))
+ CASE
--IE NUMERIC(10,2)
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('decimal','numeric')
THEN '('
+ CONVERT(VARCHAR,COLS.[precision])
+ ','
+ CONVERT(VARCHAR,COLS.[scale])
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[precision])
+ ','
+ CONVERT(VARCHAR,COLS.[scale])))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.is_identity = 1
THEN ' IDENTITY(1,1)'
ELSE ''
----WHEN COLUMNPROPERTY ( @TABLE_ID , COLS.[name] , 'IsIdentity' ) = 1
----THEN ' IDENTITY('
---- + CONVERT(VARCHAR,ISNULL(IDENT_SEED('tempdb..' + @TBLNAME),1) )
---- + ','
---- + CONVERT(VARCHAR,ISNULL(IDENT_INCR('tempdb..' + @TBLNAME),1) )
---- + ')'
----ELSE ''
END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
--IE FLOAT(53)
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('float') --,'real')
THEN
--addition: if 53, no need to specifically say (53), otherwise display it
CASE
WHEN COLS.[precision] = 53
THEN SPACE(11 - LEN(CONVERT(VARCHAR,COLS.[precision])))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,COLS.[precision])
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[precision])))
+ SPACE(7) + SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--ie VARCHAR(40)
--##############################################################################
-- COLLATE STATEMENTS in tempdb!
-- personally i do not like collation statements,
-- but included here to make it easy on those who do
--##############################################################################
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('char','varchar')
THEN CASE
WHEN COLS.[max_length] = -1
THEN '(max)'
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[max_length])))
+ SPACE(7) + SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
----collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,COLS.[max_length])
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,COLS.[max_length])))
+ SPACE(7) + SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
----collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--ie NVARCHAR(40)
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('nchar','nvarchar')
THEN CASE
WHEN COLS.[max_length] = -1
THEN '(max)'
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length] / 2))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
-- --collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,(COLS.[max_length] / 2))
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length] / 2))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
-- --collate to comment out when not desired
--+ CASE
-- WHEN COLS.collation_name IS NULL
-- THEN ''
-- ELSE ' COLLATE ' + COLS.collation_name
-- END
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--ie datetime
WHEN TYPE_NAME(COLS.[user_type_id]) IN ('datetime','money','text','image','real')
THEN SPACE(18 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ ' '
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
--IE VARBINARY(500)
WHEN TYPE_NAME(COLS.[user_type_id]) = 'varbinary'
THEN
CASE
WHEN COLS.[max_length] = -1
THEN '(max)'
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length]))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
ELSE '('
+ CONVERT(VARCHAR,(COLS.[max_length]))
+ ') '
+ SPACE(6 - LEN(CONVERT(VARCHAR,(COLS.[max_length]))))
+ SPACE(7)
+ SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
--IE INT
ELSE SPACE(16 - LEN(TYPE_NAME(COLS.[user_type_id])))
+ CASE
WHEN COLS.is_identity = 1
THEN ' IDENTITY(1,1)'
ELSE ' '
----WHEN COLUMNPROPERTY ( @TABLE_ID , COLS.[name] , 'IsIdentity' ) = 1
----THEN ' IDENTITY('
---- + CONVERT(VARCHAR,ISNULL(IDENT_SEED('tempdb..' + @TBLNAME),1) )
---- + ','
---- + CONVERT(VARCHAR,ISNULL(IDENT_INCR('tempdb..' + @TBLNAME),1) )
---- + ')'
----ELSE ' '
END
+ SPACE(2)
+ CASE
WHEN COLS.[is_nullable] = 0
THEN ' NOT NULL'
ELSE ' NULL'
END
END
+ CASE
WHEN COLS.[default_object_id] = 0
THEN ''
ELSE ' DEFAULT ' + ISNULL(def.[definition] ,'')
--optional section in case NAMED default cosntraints are needed:
--ELSE ' CONSTRAINT [' + def.name + '] DEFAULT '+ REPLACE(REPLACE(ISNULL(def.[definition] ,''),'((','('),'))',')')
--i thought it needed to be handled differently! NOT!
END --CASE cdefault
END --iscomputed
+ ','
FROM tempdb.sys.columns COLS
LEFT OUTER JOIN tempdb.sys.default_constraints DEF
ON COLS.[default_object_id] = DEF.[object_id]
LEFT OUTER JOIN tempdb.sys.computed_columns CALC
ON COLS.[object_id] = CALC.[object_id]
AND COLS.[column_id] = CALC.[column_id]
WHERE COLS.[object_id]=@TABLE_ID
ORDER BY COLS.[column_id]
--##############################################################################
--used for formatting the rest of the constraints:
--##############################################################################
SELECT
@STRINGLEN = MAX(LEN([name])) + 1
FROM tempdb.sys.objects OBJS
--##############################################################################
--PK/Unique Constraints and Indexes, using the 2005/08 INCLUDE syntax
--##############################################################################
DECLARE @Results2 TABLE (
[SCHEMA_ID] INT,
[SCHEMA_NAME] VARCHAR(255),
[OBJECT_ID] INT,
[OBJECT_NAME] VARCHAR(255),
[index_id] INT,
[index_name] VARCHAR(255),
[ROWS] BIGINT,
[SizeMB] DECIMAL(19,3),
[IndexDepth] INT,
[TYPE] INT,
[type_desc] VARCHAR(30),
[fill_factor] INT,
[is_unique] INT,
[is_primary_key] INT ,
[is_unique_constraint] INT,
[index_columns_key] VARCHAR(MAX),
[index_columns_include] VARCHAR(MAX)
--[has_filter] bit ,
--[filter_definition] VARCHAR(MAX)
)
INSERT INTO @Results2
SELECT
SCH.schema_id, SCH.[name] AS SCHEMA_NAME,
OBJS.[object_id], OBJS.[name] AS OBJECT_NAME,
IDX.index_id, ISNULL(IDX.[name], '---') AS index_name,
partitions.Rows, partitions.SizeMB, INDEXPROPERTY(OBJS.[object_id], IDX.[name], 'IndexDepth') AS IndexDepth,
IDX.type, IDX.type_desc, IDX.fill_factor,
IDX.is_unique, IDX.is_primary_key, IDX.is_unique_constraint,
ISNULL(Index_Columns.index_columns_key, '---') AS index_columns_key,
ISNULL(Index_Columns.index_columns_include, '---') AS index_columns_include
--IDX.has_filter,
--IDX.filter_definition
FROM tempdb.sys.objects OBJS
INNER JOIN tempdb.sys.schemas SCH ON OBJS.schema_id=SCH.schema_id
INNER JOIN tempdb.sys.indexes IDX ON OBJS.[object_id]=IDX.[object_id]
INNER JOIN (
SELECT
[OBJECT_ID], index_id, SUM(row_count) AS ROWS,
CONVERT(NUMERIC(19,3), CONVERT(NUMERIC(19,3), SUM(in_row_reserved_page_count+lob_reserved_page_count+row_overflow_reserved_page_count))/CONVERT(NUMERIC(19,3), 128)) AS SizeMB
FROM tempdb.sys.dm_db_partition_stats STATS
GROUP BY [OBJECT_ID], index_id
) AS partitions
ON IDX.[object_id]=partitions.[object_id]
AND IDX.index_id=partitions.index_id
CROSS APPLY (
SELECT
LEFT(index_columns_key, LEN(index_columns_key)-1) AS index_columns_key,
LEFT(index_columns_include, LEN(index_columns_include)-1) AS index_columns_include
FROM
(
SELECT
(
SELECT QUOTENAME(COLS.[name]) + CASE WHEN IXCOLS.is_descending_key = 0 THEN ' asc' ELSE ' desc' END + ',' + ' '
FROM tempdb.sys.index_columns IXCOLS
INNER JOIN tempdb.sys.columns COLS
ON IXCOLS.column_id = COLS.column_id
AND IXCOLS.[object_id] = COLS.[object_id]
WHERE IXCOLS.is_included_column = 0
AND IDX.[object_id] = IXCOLS.[object_id]
AND IDX.index_id = IXCOLS.index_id
ORDER BY key_ordinal
FOR XML PATH('')
) AS index_columns_key,
(
SELECT QUOTENAME(COLS.[name]) + ',' + ' '
FROM tempdb.sys.index_columns IXCOLS
INNER JOIN tempdb.sys.columns COLS
ON IXCOLS.column_id = COLS.column_id
AND IXCOLS.[object_id] = COLS.[object_id]
WHERE IXCOLS.is_included_column = 1
AND IDX.[object_id] = IXCOLS.[object_id]
AND IDX.index_id = IXCOLS.index_id
ORDER BY index_column_id
FOR XML PATH('')
) AS index_columns_include
) AS Index_Columns
) AS Index_Columns
WHERE SCH.[name] LIKE CASE
WHEN @SCHEMANAME = ''
THEN SCH.[name]
ELSE @SCHEMANAME
END
AND OBJS.[name] LIKE CASE
WHEN @TBLNAME = ''
THEN OBJS.[name]
ELSE @TBLNAME
END
ORDER BY
SCH.[name],
OBJS.[name],
IDX.[name]
--@Results2 table has both PK,s Uniques and indexes in thme...pull them out for adding to funal results:
SET @CONSTRAINTSQLS = ''
SET @INDEXSQLS = ''
--##############################################################################
--constriants
--##############################################################################
SELECT @CONSTRAINTSQLS = @CONSTRAINTSQLS
+ CASE
WHEN is_primary_key = 1 OR is_unique = 1
THEN @vbCrLf
+ 'CONSTRAINT ' + quotename(index_name) + ' '
+ SPACE(@STRINGLEN - LEN(index_name))
+ CASE
WHEN is_primary_key = 1
THEN ' PRIMARY KEY '
ELSE CASE
WHEN is_unique = 1
THEN ' UNIQUE '
ELSE ''
END
END
+ type_desc
+ CASE
WHEN type_desc='NONCLUSTERED'
THEN ''
ELSE ' '
END
+ ' (' + index_columns_key + ')'
+ CASE
WHEN index_columns_include <> '---'
THEN ' INCLUDE (' + index_columns_include + ')'
ELSE ''
END
+ CASE
WHEN fill_factor <> 0
THEN ' WITH FILLFACTOR = ' + CONVERT(VARCHAR(30),fill_factor)
ELSE ''
END
ELSE ''
END + ','
FROM @Results2
WHERE [type_desc] != 'HEAP'
AND is_primary_key = 1
OR is_unique = 1
ORDER BY
is_primary_key DESC,
is_unique DESC
--##############################################################################
--indexes
--##############################################################################
SELECT @INDEXSQLS = @INDEXSQLS
+ CASE
WHEN is_primary_key = 0 OR is_unique = 0
THEN @vbCrLf
+ 'CREATE ' + type_desc + ' INDEX ' + quotename(index_name) + ' '
+ @vbCrLf
+ ' ON ' + quotename([schema_name]) + '.' + quotename([OBJECT_NAME])
+ ' (' + index_columns_key + ')'
+ CASE
WHEN index_columns_include <> '---'
THEN @vbCrLf + ' INCLUDE (' + index_columns_include + ')'
ELSE ''
END
--2008 filtered indexes syntax
--+ CASE
-- WHEN has_filter = 1
-- THEN @vbCrLf + ' WHERE ' + filter_definition
-- ELSE ''
-- END
+ CASE
WHEN fill_factor <> 0
THEN @vbCrLf + ' WITH FILLFACTOR = ' + CONVERT(VARCHAR(30),fill_factor)
ELSE ''
END
END
FROM @Results2
WHERE [type_desc] != 'HEAP'
AND is_primary_key = 0
AND is_unique = 0
ORDER BY
is_primary_key DESC,
is_unique DESC
IF @INDEXSQLS <> ''
SET @INDEXSQLS = @vbCrLf + 'GO' + @vbCrLf + @INDEXSQLS
--##############################################################################
--CHECK Constraints
--##############################################################################
SET @CHECKCONSTSQLS = ''
SELECT
@CHECKCONSTSQLS = @CHECKCONSTSQLS
+ @vbCrLf
+ ISNULL('CONSTRAINT ' + quotename(OBJS.[name]) + ' '
+ SPACE(@STRINGLEN - LEN(OBJS.[name]))
+ ' CHECK ' + ISNULL(CHECKS.definition,'')
+ ',','')
FROM tempdb.sys.objects OBJS
INNER JOIN tempdb.sys.check_constraints CHECKS ON OBJS.[object_id] = CHECKS.[object_id]
WHERE OBJS.type = 'C'
AND OBJS.parent_object_id = @TABLE_ID
--##############################################################################
--FOREIGN KEYS
--##############################################################################
SET @FKSQLS = '' ;
SELECT
@FKSQLS=@FKSQLS
+ @vbCrLf
+ 'CONSTRAINT ' + quotename(OBJECT_NAME(constid)) +''
+ SPACE(@STRINGLEN - LEN(OBJECT_NAME(constid) ))
+ ' FOREIGN KEY (' + quotename(COL_NAME(fkeyid,fkey))
+ ') REFERENCES ' + quotename(OBJECT_NAME(rkeyid))
+'(' + quotename(COL_NAME(rkeyid,rkey)) + '),'
FROM sysforeignkeys FKEYS
WHERE fkeyid = @TABLE_ID
--##############################################################################
--RULES
--##############################################################################
SET @RULESCONSTSQLS = ''
SELECT
@RULESCONSTSQLS = @RULESCONSTSQLS
+ ISNULL(
@vbCrLf
+ 'if not exists(SELECT [name] FROM tempdb.sys.objects WHERE TYPE=''R'' AND schema_id = ' + CONVERT(VARCHAR(30),OBJS.schema_id) + ' AND [name] = ''' + quotename(OBJECT_NAME(COLS.[rule_object_id])) + ''')' + @vbCrLf
+ MODS.definition + @vbCrLf + 'GO' + @vbCrLf
+ 'EXEC sp_binderule ' + quotename(OBJS.[name]) + ', ''' + quotename(OBJECT_NAME(COLS.[object_id])) + '.' + quotename(COLS.[name]) + '''' + @vbCrLf + 'GO' ,'')
FROM tempdb.sys.columns COLS
INNER JOIN tempdb.sys.objects OBJS
ON OBJS.[object_id] = COLS.[object_id]
INNER JOIN tempdb.sys.sql_modules MODS
ON COLS.[rule_object_id] = MODS.[object_id]
WHERE COLS.[rule_object_id] <> 0
AND COLS.[object_id] = @TABLE_ID
--##############################################################################
--TRIGGERS
--##############################################################################
SET @TRIGGERSTATEMENT = ''
SELECT
@TRIGGERSTATEMENT = @TRIGGERSTATEMENT + @vbCrLf + MODS.[definition] + @vbCrLf + 'GO'
FROM tempdb.sys.sql_modules MODS
WHERE [OBJECT_ID] IN(SELECT
[OBJECT_ID]
FROM tempdb.sys.objects OBJS
WHERE TYPE = 'TR'
AND [parent_object_id] = @TABLE_ID)
IF @TRIGGERSTATEMENT <> ''
SET @TRIGGERSTATEMENT = @vbCrLf + 'GO' + @vbCrLf + @TRIGGERSTATEMENT
--##############################################################################
--NEW SECTION QUERY ALL EXTENDED PROPERTIES
--##############################################################################
SET @EXTENDEDPROPERTIES = ''
SELECT @EXTENDEDPROPERTIES =
@EXTENDEDPROPERTIES + @vbCrLf +
'EXEC tempdb.sys.sp_addextendedproperty
@name = N''' + [name] + ''', @value = N''' + REPLACE(CONVERT(VARCHAR(MAX),[VALUE]),'''','''''') + ''',
@level0type = N''SCHEMA'', @level0name = ' + quotename(@SCHEMANAME + ',
@level1type = N''TABLE'', @level1name = [' + @TBLNAME) + '];'
--SELECT objtype, objname, name, value
FROM fn_listextendedproperty (NULL, 'schema', @SCHEMANAME, 'table', @TBLNAME, NULL, NULL);
--OMacoder suggestion for column extended properties http://www.sqlservercentral.com/Forums/FindPost1651606.aspx
SELECT @EXTENDEDPROPERTIES =
@EXTENDEDPROPERTIES + @vbCrLf +
'EXEC sys.sp_addextendedproperty
@name = N''' + [name] + ''', @value = N''' + REPLACE(convert(varchar(max),[value]),'''','''''') + ''',
@level0type = N''SCHEMA'', @level0name = ' + quotename(@SCHEMANAME) + ',
@level1type = N''TABLE'', @level1name = ' + quotename(@TBLNAME) + ',
@level2type = N''COLUMN'', @level2name = ' + quotename([objname]) + ';'
--SELECT objtype, objname, name, value
FROM fn_listextendedproperty (NULL, 'schema', @SCHEMANAME, 'table', @TBLNAME, 'column', NULL)
IF @EXTENDEDPROPERTIES <> ''
SET @EXTENDEDPROPERTIES = @vbCrLf + 'GO' + @vbCrLf + @EXTENDEDPROPERTIES
--##############################################################################
--FINAL CLEANUP AND PRESENTATION
--##############################################################################
--at this point, there is a trailing comma, or it blank
SELECT
@FINALSQL = @FINALSQL
+ @CONSTRAINTSQLS
+ @CHECKCONSTSQLS
+ @FKSQLS
--note that this trims the trailing comma from the end of the statements
SET @FINALSQL = SUBSTRING(@FINALSQL,1,LEN(@FINALSQL) -1) ;
SET @FINALSQL = @FINALSQL + ')' + @vbCrLf ;
SET @input = @vbCrLf
+ @FINALSQL
+ @INDEXSQLS
+ @RULESCONSTSQLS
+ @TRIGGERSTATEMENT
+ @EXTENDEDPROPERTIES
--ten years worth of days from todays date:
;WITH E01(N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1), -- 10 or 10E01 rows
E02(N) AS (SELECT 1 FROM E01 a, E01 b), -- 100 or 10E02 rows
E04(N) AS (SELECT 1 FROM E02 a, E02 b), -- 10,000 or 10E04 rows
E08(N) AS (SELECT 1 FROM E04 a, E04 b), --100,000,000 or 10E08 rows
--E16(N) AS (SELECT 1 FROM E08 a, E08 b), --10E16 or more rows than you'll EVER need,
Tally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E08),
ItemSplit(
ItemOrder,
Item
) AS (
SELECT N,
SUBSTRING(@vbCrLf + @input + @vbCrLf,N + DATALENGTH(@vbCrLf),CHARINDEX(@vbCrLf,@vbCrLf + @input + @vbCrLf,N + DATALENGTH(@vbCrLf)) - N - DATALENGTH(@vbCrLf))
FROM Tally
WHERE N < DATALENGTH(@vbCrLf + @input)
--WHERE N < DATALENGTH(@vbCrLf + @input) -- REMOVED added @vbCrLf
AND SUBSTRING(@vbCrLf + @input + @vbCrLf,N,DATALENGTH(@vbCrLf)) = @vbCrLf --Notice how we find the delimiter
)
SELECT
--row_number() over (order by ItemOrder) as ItemID,
Item
FROM ItemSplit
RETURN;
END --PROC
GO
--#################################################################################################
print 'created PROCEDURE sp_GetTableDef'
GO
--Mark as a system object
EXECUTE sp_ms_marksystemobject 'sp_GetTableDef'
--GRANT EXECUTE ON dbo.sp_GetTableDef TO PUBLIC;
--#################################################################################################
GO
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment