Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. use master; -- A bit naughty, since we shouldn't change the master database
  2. GO
  3. /*
  4.     Creates an empty replica of a table - i.e. a new table with the same columns and indexes, but with a different name.
  5.     This is useful for creating switch-in / switch-out tables.
  6.  
  7.     Features currently supported:
  8.             Heaps, Clustered Indexes and non-clustered indexes, Partitioned Indexes.
  9.             Included Columns.
  10.             Column Defaults.
  11.             Check constraints.
  12.             Sparse columns.
  13.  
  14.     Features currently not supported:
  15.             Default Bindings.
  16.             XML indexes.
  17.             Column Store indexes.                
  18. */
  19. CREATE PROC [dbo].[sp_CloneTable]
  20.     @table                  VARCHAR(100) ,          -- The name of the table to be cloned.
  21.     @new_schema             VARCHAR(100) = null,    -- The schema in which to create the new table. Leave null to create new table in same schema.
  22.     @new_table              VARCHAR(100) = null,    -- The name of the target table. Leave null to keep original table name.
  23.     @enable_index_type      int          = 2        -- Controls which indexes to enable on the target. 2 = clustered & non-clustered, 1 = clustered only, 0 = none.
  24. AS    
  25.     SET NOCOUNT ON;
  26.  
  27.     DECLARE @object_id int = OBJECT_ID(@table)
  28.        
  29.     IF @object_id IS NULL RAISERROR ('Source table does not exists',16,0);
  30.        
  31.     IF @new_schema IS NULL and @new_table IS NULL RAISERROR ('The new table must be given a different name and/or schema',16,0);
  32.  
  33.     SET @new_schema = ISNULL(@new_schema, OBJECT_SCHEMA_NAME(@object_id));
  34.     SET @new_table  = ISNULL(@new_table , OBJECT_NAME(@object_id));
  35.  
  36.     DECLARE @SQL VARCHAR(MAX) = '';
  37.  
  38.     SET @SQL = @SQL + 'IF EXISTS(SELECT * FROM sys.tables WHERE object_id = OBJECT_ID(''' + QUOTENAME(@new_schema) + '.' + QUOTENAME(@new_table) + ''')) DROP TABLE ' + @new_schema + '.' + @new_table + ';' + CHAR(13) + CHAR(13);
  39.  
  40.  
  41.     WITH index_columns AS (
  42.         SELECT  ic.index_id,
  43.                 included          = ic.is_included_column,
  44.                 ordinal           = ic.key_ordinal,
  45.                 column_name       = c.name,
  46.                 partition_ordinal = ic.partition_ordinal,
  47.                 comma_column_name = ', ' + c.name,
  48.                 comma_column_key  = ', ' + c.name + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE '' END
  49.         FROM sys.index_columns ic
  50.         JOIN sys.columns c on c.column_id = ic.column_id AND c.object_id = ic.object_id
  51.         WHERE ic.object_id = @object_id
  52.     ), indexes AS (
  53.         SELECT  i.is_primary_key,
  54.                 i.type,
  55.                 i.is_unique_constraint,
  56.                 i.name,
  57.                 create_stmt  = 'CREATE ' + CASE WHEN i.is_unique = 1 THEN 'UNIQUE ' ELSE '' END + CASE WHEN i.type = 1 THEN 'CLUSTERED ' ELSE '' END + 'INDEX ',
  58.                 columns      = (SELECT [data()] = column_name FROM index_columns ic WHERE ic.index_id = i.index_id and included = 0 ORDER BY ordinal FOR XML PATH('')),
  59.                 key_columns  = STUFF((SELECT [data()] = comma_column_key FROM index_columns ic WHERE ic.index_id = i.index_id and included = 0 ORDER BY ordinal FOR XML PATH('')) ,1,2,''),
  60.                 included     = STUFF((SELECT [data()] = comma_column_name FROM index_columns ic WHERE ic.index_id = i.index_id and included = 1 FOR XML PATH('')) ,1,2,''),
  61.                 pk_options   = ISNULL('WITH(DATA_COMPRESSION=' + data_compression_desc + ')', ''),
  62.                 options      = ' WITH (  PAD_INDEX = '       + CASE is_padded WHEN 1 THEN 'ON' ELSE 'OFF' END
  63.                             + ', ALLOW_ROW_LOCKS = '        + CASE allow_row_locks WHEN 1 THEN 'ON' ELSE 'OFF' END
  64.                             + ', ALLOW_PAGE_LOCKS = '       + CASE allow_page_locks WHEN 1 THEN 'ON' ELSE 'OFF' END
  65.                             + ISNULL(', FILLFACTOR = '      + NULLIF(CAST(fill_factor AS VARCHAR(10)), '0') , '')
  66.                             + ISNULL(', IGNORE_DUP_KEY = '  + CASE ignore_dup_key WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' END, '')
  67.                             + ISNULL(', DATA_COMPRESSION = ' + data_compression_desc, '')
  68.                             + ISNULL(', STATISTICS_NORECOMPUTE = ' + CASE (SELECT TOP 1 no_recompute FROM sys.stats stats WHERE i.object_id = stats.object_id and i.index_id = stats.stats_id)
  69.                                                                         WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' END, '')
  70.                             + ')',
  71.                 filegroup    = COALESCE(
  72.                                 (SELECT TOP 1 ' ON ' + ps.name + '('
  73.                                     +  STUFF((SELECT [data()]=comma_column_key FROM index_columns ic WHERE ic.index_id = i.index_id and partition_ordinal > 0 ORDER BY partition_ordinal FOR XML PATH('')) ,1,2,'')
  74.                                     + ')'
  75.                                     FROM sys.partition_schemes ps
  76.                                     JOIN sys.partition_functions pf ON pf.function_id = ps.function_id                                 
  77.                                     WHERE ps.data_space_id = i.data_space_id
  78.                                 ),
  79.                                 (SELECT TOP 1 ' ON ' + QUOTENAME(name) FROM sys.filegroups WHERE data_space_id = i.data_space_id)
  80.                                 ,'')
  81.         FROM sys.indexes i
  82.         OUTER APPLY (SELECT data_compression_desc FROM sys.partitions part WHERE i.object_id = part.object_id  and i.index_id = part.index_id
  83.                      GROUP BY data_compression_desc HAVING COUNT(*) = 1) d
  84.            
  85.         WHERE i.object_id = @object_id
  86.     )
  87.     SELECT @SQL = @SQL
  88.             + 'CREATE TABLE ' + QUOTENAME(@new_schema) + '.' + QUOTENAME(@new_table) + CHAR(13)
  89.             + '(' + CHAR(13)
  90.             + STUFF( (SELECT [data()] = '^*^,     ' + QUOTENAME(c.name) + ' '
  91.                     + CASE WHEN c.is_computed = 1 THEN ' AS ' + cc.definition + CASE WHEN cc.is_persisted = 1 THEN ' PERSISTED' ELSE '' END
  92.                         ELSE
  93.                         t.name
  94.                         +  CASE WHEN t.user_type_id in (165,167,173,175,231,239)    -- varbinary,varbinary,varchar,binary,char,nvarchar,nchar
  95.                                 THEN '(' + REPLACE(CONVERT(VARCHAR(20), c.max_length),'-1','max') + ')'
  96.                                 WHEN t.user_type_id in (40,42)                      -- date/datetime2
  97.                                 THEN '(' + CONVERT(VARCHAR(20), c.scale) + ')' 
  98.                                 WHEN t.user_type_id in (106,108)                    -- decimal/numeric
  99.                                 THEN '(' + CONVERT(VARCHAR(20), c.precision) + ',' + CONVERT(VARCHAR(20), c.scale) + ')'
  100.                                 ELSE '' END
  101.                         +  CASE WHEN c.is_sparse   = 1 THEN ' SPARSE' ELSE '' END
  102.                         +  CASE WHEN c.is_identity = 1 THEN ' IDENTITY(1,1)' ELSE '' END    -- currently, no support identity seeds
  103.                         +  CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END   
  104.                         +  ISNULL( ' DEFAULT ' + dc.definition,'')
  105.                         END
  106.                     FROM sys.columns c
  107.                     JOIN sys.types t ON t.user_type_id = c.user_type_id
  108.                     LEFT JOIN sys.computed_columns cc on cc.object_id = c.object_id and cc.column_id = c.column_id
  109.                     LEFT JOIN sys.default_constraints dc on dc.parent_object_id = c.object_id and dc.parent_column_id = c.column_id
  110.                     WHERE c.object_id = @object_id
  111.                     FOR XML PATH(''))
  112.             ,1,4,'')
  113.                
  114.             + ISNULL((SELECT ',' + CHAR(13) + '      CONSTRAINT ' + QUOTENAME('PK_' + REPLACE(REPLACE(@new_table, '[',''),']',''))
  115.                                 + ' PRIMARY KEY ' + CASE WHEN i.type <> 1 THEN 'NON' ELSE '' END
  116.                                 + 'CLUSTERED (' + i.key_columns + ') ' + pk_options + filegroup
  117.                         FROM indexes i where i.is_primary_key = 1)
  118.                         ,'')
  119.  
  120.             + ISNULL((SELECT [data()] = '^*^        CONSTRAINT ' + QUOTENAME(i.name) + ' UNIQUE (' + i.key_columns + ')' + filegroup FROM indexes i where i.is_primary_key = 0 and i.is_unique_constraint = 1 FOR XML PATH('')),'')
  121.              
  122.             + ISNULL((SELECT [data()] = ',^*^     CONSTRAINT ' + QUOTENAME(cc.name) + ' CHECK ' + cc.definition
  123.                       FROM sys.check_constraints cc WHERE cc.parent_object_id = @object_id FOR XML PATH(''))  ,'')
  124.            
  125.             + CHAR(13)
  126.             + ') '
  127.            
  128.             + ISNULL((SELECT TOP 1 filegroup FROM indexes i WHERE i.type in (0,1)),'') + ';' + CHAR(13)
  129.  
  130.             + ISNULL(
  131.                 (SELECT [data()] = '^*^' + i.create_stmt
  132.                         + QUOTENAME('IX ' + @new_schema + '.' + @new_table + ' ' + i.columns)
  133.                         + ' ON ' + QUOTENAME(@new_schema) + '.' + QUOTENAME(@new_table)
  134.                         + ' (' + i.key_columns + ' )'
  135.                         + ISNULL(' INCLUDE (' + i.included + ')','') + options + filegroup + ';'
  136.                 FROM indexes i
  137.                 WHERE i.is_primary_key = 0 and i.is_unique_constraint = 0
  138.                 FOR XML PATH(''))              
  139.                 ,'')
  140.             + CHAR(13)
  141.            
  142.             + ISNULL(
  143.                 (SELECT [data()] =
  144.                     '^*^ALTER INDEX ' + CASE WHEN i.is_primary_key = 1 THEN QUOTENAME('PK_' + REPLACE(REPLACE(@new_table, '[',''),']',''))  
  145.                                                                     ELSE QUOTENAME('IX ' + @new_schema + '.' + @new_table + ' ' + i.columns) END
  146.                     + ' ON ' + QUOTENAME(@new_schema) + '.' + QUOTENAME(@new_table)
  147.                     + ' DISABLE;'
  148.                 FROM indexes i
  149.                 WHERE i.type > @enable_index_type
  150.                 FOR XML PATH(''))              
  151.                ,'');
  152.  
  153.     SET @SQL = REPLACE(REPLACE(REPLACE(@SQL, '^*^', CHAR(13)) ,'&lt;','<'),'&gt;','>')
  154.    
  155.     EXEC (@SQL);
  156. GO
  157.  
  158.  
  159. EXEC sp_ms_marksystemobject 'sp_CloneTable'