AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 18059
Accepted
jcho360
jcho360
Asked: 2012-05-18 04:26:03 +0800 CST2012-05-18 04:26:03 +0800 CST 2012-05-18 04:26:03 +0800 CST

复制表的完整结构

  • 772

使用某些方法,当您创建表的副本时,您会丢失索引、PK、FK 等。例如在 SQL Server 中,我可以说:

select * into dbo.table2 from dbo.table1;

这只是表格的简单副本;缺少所有索引/约束。如何复制表结构(不使用备份)?

我主要希望手动执行此操作,但如果不可能,我会接受任何解决方案。

sql-server index
  • 7 7 个回答
  • 162185 Views

7 个回答

  • Voted
  1. Best Answer
    Aaron Bertrand
    2012-05-18T04:34:24+08:002012-05-18T04:34:24+08:00

    当然,您可以使用 UI 相对简单地编写表格脚本:

    在此处输入图像描述

    这将输出一个CREATE TABLE脚本,您只需搜索并用新名称替换旧名称(并验证具有新名称的对象不存在)。

    但是,如果您尝试自动执行此操作(例如,在代码中生成创建表脚本),它会更麻烦一些。上面的脚本选项不只是CREATE TABLE从元数据中的单个位置提取整个 DDL;它在代码的幕后做了一大堆魔法来生成最终的CREATE TABLE脚本(你可以使用 Profiler 来查看它从哪里获取数据,但你看不到它是如何组装它的)。我为此建议了一个选项:

    http://connect.microsoft.com/SQLServer/feedback/details/273934

    然而,这得到了很少的选票,并很快被微软否决。您可能会发现使用 3rd 方工具来生成模式更值得(我已经在博客上写过这个)。

    在 SQL Server 2012 中,有新的元数据函数可以让您比 2005、2008 和 2008 R2 中的工作更接近,将元数据中的列信息拼凑在一起(这有很多警告,例如,如果它是decimal 你必须添加精度/比例,如果 [n[var[char]] 你必须添加长度规范,如果 n[var]char 你必须将 max_length 减半,如果它是 MAX 你必须将 -1 更改为 MAX 等)。在 SQL Server 2012 中,这部分要简单一些:

    SELECT name, system_type_name, is_nullable FROM
      sys.dm_exec_describe_first_result_set('select * from sys.objects', NULL, 0)
    

    结果:

    name                   system_type_name  is_nullable
    --------------------   ----------------  -----------
    name                   nvarchar(128)     0
    object_id              int               0
    principal_id           int               1
    schema_id              int               0
    parent_object_id       int               0
    type                   char(2)           0
    type_desc              nvarchar(60)      1
    create_date            datetime          0
    modify_date            datetime          0
    is_ms_shipped          bit               0
    is_published           bit               0
    is_schema_published    bit               0
    

    我也写过关于这个的博客。

    CREATE TABLE可以说,这比使用 的复杂方法更接近您的目标陈述sys.columns,但仍有很多工作要做。键、约束、行选项中的文本、文件组信息、压缩设置、索引等。这是一个很长的列表,我将再次建议您为此使用 3rd 方工具,而不是冒着重复一遍的风险- 使用类比,重新发明轮子。

    综上所述,如果您需要通过代码执行此操作,但您可以在 SQL Server 之外执行此操作,则可以考虑 SMO/PowerShell。请参阅此技巧和Scripter.Script() 方法。

    • 31
  2. user31215
    2013-12-04T03:36:38+08:002013-12-04T03:36:38+08:00

    我写了这个 sp 来自动创建包含所有东西的模式,pk,fk,分区,约束......

    重要的!!在执行之前

    create type TestTableType as table (ObjectID int)
    

    这里是 SP:

        SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    
        --*************************************************************************************************'
    --    La procedura crea lo script di una tabella
    --    Tabella   : xxxxx
    --    Creata da : E.Mantovanelli
    --    Data creazione : 28-06-2012
    --    Data modifica: 28-06-2012
    --*************************************************************************************************'
    
    /*
        --      ID----|-----Data-----|--    User        ---------   | ----  Note
                            20-11-2013      E.Mantovanelli                  distinzione schema delle tabelle
                                                                            estrazione da db selezionato
                                                                            aggiunta estrazione partizione
    */
    
    CREATE PROCEDURE [dbo].[util_ScriptTable] 
         @DBName SYSNAME
        ,@schema sysname
        ,@TableName SYSNAME
        ,@IncludeConstraints BIT = 1
        ,@IncludeIndexes BIT = 1
        ,@NewTableSchema sysname
        ,@NewTableName SYSNAME = NULL
        ,@UseSystemDataTypes BIT = 0
        ,@script varchar(max) output
    AS 
    BEGIN try
        if not exists (select * from sys.types where name = 'TestTableType')
            create type TestTableType as table (ObjectID int)--drop type TestTableType
    
        declare @sql nvarchar(max)
    
        DECLARE @MainDefinition TABLE (FieldValue VARCHAR(200))
        --DECLARE @DBName SYSNAME
        DECLARE @ClusteredPK BIT
        DECLARE @TableSchema NVARCHAR(255)
    
        --SET @DBName = DB_NAME(DB_ID())
        SELECT @TableName = name FROM sysobjects WHERE id = OBJECT_ID(@TableName)
    
        DECLARE @ShowFields TABLE (FieldID INT IDENTITY(1,1)
                                            ,DatabaseName VARCHAR(100)
                                            ,TableOwner VARCHAR(100)
                                            ,TableName VARCHAR(100)
                                            ,FieldName VARCHAR(100)
                                            ,ColumnPosition INT
                                            ,ColumnDefaultValue VARCHAR(100)
                                            ,ColumnDefaultName VARCHAR(100)
                                            ,IsNullable BIT
                                            ,DataType VARCHAR(100)
                                            ,MaxLength varchar(10)
                                            ,NumericPrecision INT
                                            ,NumericScale INT
                                            ,DomainName VARCHAR(100)
                                            ,FieldListingName VARCHAR(110)
                                            ,FieldDefinition CHAR(1)
                                            ,IdentityColumn BIT
                                            ,IdentitySeed INT
                                            ,IdentityIncrement INT
                                            ,IsCharColumn BIT 
                                            ,IsComputed varchar(255))
    
        DECLARE @HoldingArea TABLE(FldID SMALLINT IDENTITY(1,1)
                                            ,Flds VARCHAR(4000)
                                            ,FldValue CHAR(1) DEFAULT(0))
    
        DECLARE @PKObjectID TABLE(ObjectID INT)
    
        DECLARE @Uniques TABLE(ObjectID INT)
    
        DECLARE @HoldingAreaValues TABLE(FldID SMALLINT IDENTITY(1,1)
                                                    ,Flds VARCHAR(4000)
                                                    ,FldValue CHAR(1) DEFAULT(0))
    
        DECLARE @Definition TABLE(DefinitionID SMALLINT IDENTITY(1,1)
                                            ,FieldValue VARCHAR(200))
    
    
      set @sql=
      '
      use '+@DBName+'
      SELECT distinct DB_NAME()
                ,TABLE_SCHEMA
                ,TABLE_NAME
                ,''[''+COLUMN_NAME+'']'' as COLUMN_NAME
                ,CAST(ORDINAL_POSITION AS INT)
                ,COLUMN_DEFAULT
                ,dobj.name AS ColumnDefaultName
                ,CASE WHEN c.IS_NULLABLE = ''YES'' THEN 1 ELSE 0 END
                ,DATA_TYPE
                ,case CHARACTER_MAXIMUM_LENGTH when -1 then ''max'' else CAST(CHARACTER_MAXIMUM_LENGTH AS varchar) end--CAST(CHARACTER_MAXIMUM_LENGTH AS INT)
                ,CAST(NUMERIC_PRECISION AS INT)
                ,CAST(NUMERIC_SCALE AS INT)
                ,DOMAIN_NAME
                ,COLUMN_NAME + '',''
                ,'''' AS FieldDefinition
                ,CASE WHEN ic.object_id IS NULL THEN 0 ELSE 1 END AS IdentityColumn
                ,CAST(ISNULL(ic.seed_value,0) AS INT) AS IdentitySeed
                ,CAST(ISNULL(ic.increment_value,0) AS INT) AS IdentityIncrement
                ,CASE WHEN st.collation_name IS NOT NULL THEN 1 ELSE 0 END AS IsCharColumn 
                ,cc.definition 
                FROM INFORMATION_SCHEMA.COLUMNS c
                JOIN sys.columns sc ON  c.TABLE_NAME = OBJECT_NAME(sc.object_id) AND c.COLUMN_NAME = sc.Name
                LEFT JOIN sys.identity_columns ic ON c.TABLE_NAME = OBJECT_NAME(ic.object_id) AND c.COLUMN_NAME = ic.Name
                JOIN sys.types st ON COALESCE(c.DOMAIN_NAME,c.DATA_TYPE) = st.name
                LEFT OUTER JOIN sys.objects dobj ON dobj.object_id = sc.default_object_id AND dobj.type = ''D''
                left join sys.computed_columns cc on c.TABLE_NAME=OBJECT_NAME(cc.object_id) and sc.column_id=cc.column_id
        WHERE c.TABLE_NAME = @TableName and c.TABLE_SCHEMA=@schema 
        ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION
        '
    
      print @sql
      INSERT INTO @ShowFields( DatabaseName
                                        ,TableOwner
                                        ,TableName
                                        ,FieldName
                                        ,ColumnPosition
                                        ,ColumnDefaultValue
                                        ,ColumnDefaultName
                                        ,IsNullable
                                        ,DataType
                                        ,MaxLength
                                        ,NumericPrecision
                                        ,NumericScale
                                        ,DomainName
                                        ,FieldListingName
                                        ,FieldDefinition
                                        ,IdentityColumn
                                        ,IdentitySeed
                                        ,IdentityIncrement
                                        ,IsCharColumn
                                        ,IsComputed)
    
        exec sp_executesql @sql,
                           N'@TableName varchar(50),@schema varchar(50)',
                           @TableName=@TableName,@schema=@schema            
        /*
        SELECT @DBName--DB_NAME()
                ,TABLE_SCHEMA
                ,TABLE_NAME
                ,COLUMN_NAME
                ,CAST(ORDINAL_POSITION AS INT)
                ,COLUMN_DEFAULT
                ,dobj.name AS ColumnDefaultName
                ,CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END
                ,DATA_TYPE
                ,CAST(CHARACTER_MAXIMUM_LENGTH AS INT)
                ,CAST(NUMERIC_PRECISION AS INT)
                ,CAST(NUMERIC_SCALE AS INT)
                ,DOMAIN_NAME
                ,COLUMN_NAME + ','
                ,'' AS FieldDefinition
                ,CASE WHEN ic.object_id IS NULL THEN 0 ELSE 1 END AS IdentityColumn
                ,CAST(ISNULL(ic.seed_value,0) AS INT) AS IdentitySeed
                ,CAST(ISNULL(ic.increment_value,0) AS INT) AS IdentityIncrement
                ,CASE WHEN st.collation_name IS NOT NULL THEN 1 ELSE 0 END AS IsCharColumn 
                FROM INFORMATION_SCHEMA.COLUMNS c
                JOIN sys.columns sc ON  c.TABLE_NAME = OBJECT_NAME(sc.object_id) AND c.COLUMN_NAME = sc.Name
                LEFT JOIN sys.identity_columns ic ON c.TABLE_NAME = OBJECT_NAME(ic.object_id) AND c.COLUMN_NAME = ic.Name
                JOIN sys.types st ON COALESCE(c.DOMAIN_NAME,c.DATA_TYPE) = st.name
                LEFT OUTER JOIN sys.objects dobj ON dobj.object_id = sc.default_object_id AND dobj.type = 'D'
    
        WHERE c.TABLE_NAME = @TableName
        ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION
        */
        SELECT TOP 1 @TableSchema = TableOwner FROM @ShowFields
    
        INSERT INTO @HoldingArea (Flds) VALUES('(')
    
        INSERT INTO @Definition(FieldValue)VALUES('CREATE TABLE ' + CASE WHEN @NewTableName IS NOT NULL THEN @DBName + '.' + @NewTableSchema + '.' + @NewTableName ELSE @DBName + '.' + @TableSchema + '.' + @TableName END)
        INSERT INTO @Definition(FieldValue)VALUES('(')
        INSERT INTO @Definition(FieldValue)
        SELECT   CHAR(10) + FieldName + ' ' + 
            --CASE WHEN DomainName IS NOT NULL AND @UseSystemDataTypes = 0 THEN DomainName + CASE WHEN IsNullable = 1 THEN ' NULL ' ELSE ' NOT NULL ' END ELSE UPPER(DataType) +CASE WHEN IsCharColumn = 1 THEN '(' + CAST(MaxLength AS VARCHAR(10)) + ')' ELSE '' END +CASE WHEN IdentityColumn = 1 THEN ' IDENTITY(' + CAST(IdentitySeed AS VARCHAR(5))+ ',' + CAST(IdentityIncrement AS VARCHAR(5)) + ')' ELSE '' END +CASE WHEN IsNullable = 1 THEN ' NULL ' ELSE ' NOT NULL ' END +CASE WHEN ColumnDefaultName IS NOT NULL AND @IncludeConstraints = 1 THEN 'CONSTRAINT [' + ColumnDefaultName + '] DEFAULT' + UPPER(ColumnDefaultValue) ELSE '' END END + CASE WHEN FieldID = (SELECT MAX(FieldID) FROM @ShowFields) THEN '' ELSE ',' END 
    
            CASE WHEN DomainName IS NOT NULL AND @UseSystemDataTypes = 0 THEN DomainName + 
                CASe WHEN IsNullable = 1 THEN ' NULL ' 
                ELSE ' NOT NULL ' 
                END 
            ELSE 
                case when IsComputed is null then
                    UPPER(DataType) +
                    CASE WHEN IsCharColumn = 1 THEN '(' + CAST(MaxLength AS VARCHAR(10)) + ')' 
                    ELSE 
                        CASE WHEN DataType = 'numeric' THEN '(' + CAST(NumericPrecision AS VARCHAR(10))+','+ CAST(NumericScale AS VARCHAR(10)) + ')' 
                        ELSE
                            CASE WHEN DataType = 'decimal' THEN '(' + CAST(NumericPrecision AS VARCHAR(10))+','+ CAST(NumericScale AS VARCHAR(10)) + ')' 
                            ELSE '' 
                            end  
                        end 
                    END +
                    CASE WHEN IdentityColumn = 1 THEN ' IDENTITY(' + CAST(IdentitySeed AS VARCHAR(5))+ ',' + CAST(IdentityIncrement AS VARCHAR(5)) + ')' 
                    ELSE '' 
                    END +
                    CASE WHEN IsNullable = 1 THEN ' NULL ' 
                    ELSE ' NOT NULL ' 
                    END +
                    CASE WHEN ColumnDefaultName IS NOT NULL AND @IncludeConstraints = 1 THEN 'CONSTRAINT [' + replace(ColumnDefaultName,@TableName,@NewTableName) + '] DEFAULT' + UPPER(ColumnDefaultValue) 
                    ELSE '' 
                    END 
                else
                    ' as '+IsComputed+' '
                end
            END + 
            CASE WHEN FieldID = (SELECT MAX(FieldID) FROM @ShowFields) THEN '' 
            ELSE ',' 
            END 
    
        FROM    @ShowFields
    
        IF @IncludeConstraints = 1
            BEGIN    
    
            set @sql=
            '
            use '+@DBName+'
            SELECT  distinct  '',CONSTRAINT ['' + replace(name,@TableName,@NewTableName) + ''] FOREIGN KEY ('' + ParentColumns + '') REFERENCES ['' + ReferencedObject + '']('' + ReferencedColumns + '')'' 
               FROM ( SELECT   ReferencedObject = OBJECT_NAME(fk.referenced_object_id), ParentObject = OBJECT_NAME(parent_object_id),fk.name
                    ,   REVERSE(SUBSTRING(REVERSE((   SELECT cp.name + '',''   
                    FROM   sys.foreign_key_columns fkc   
                    JOIN sys.columns cp ON fkc.parent_object_id = cp.object_id AND fkc.parent_column_id = cp.column_id   
                    WHERE fkc.constraint_object_id = fk.object_id   FOR XML PATH('''')   )), 2, 8000)) ParentColumns,   
                    REVERSE(SUBSTRING(REVERSE((   SELECT cr.name + '',''   
                    FROM   sys.foreign_key_columns fkc  
                    JOIN sys.columns cr ON fkc.referenced_object_id = cr.object_id AND fkc.referenced_column_id = cr.column_id
                    WHERE fkc.constraint_object_id = fk.object_id   FOR XML PATH('''')   )), 2, 8000)) ReferencedColumns   
                    FROM sys.foreign_keys fk    
                        inner join sys.schemas s on fk.schema_id=s.schema_id and s.name=@schema) a    
                WHERE ParentObject = @TableName    
            '
    
            print @sql
    
            INSERT INTO @Definition(FieldValue)
            exec sp_executesql @sql,
                       N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50)',
                           @TableName=@TableName,@NewTableName=@NewTableName,@schema=@schema
                /*
               SELECT    ',CONSTRAINT [' + name + '] FOREIGN KEY (' + ParentColumns + ') REFERENCES [' + ReferencedObject + '](' + ReferencedColumns + ')'  
               FROM ( SELECT   ReferencedObject = OBJECT_NAME(fk.referenced_object_id), ParentObject = OBJECT_NAME(parent_object_id),fk.name
                    ,   REVERSE(SUBSTRING(REVERSE((   SELECT cp.name + ','   
                    FROM   sys.foreign_key_columns fkc   
                    JOIN sys.columns cp ON fkc.parent_object_id = cp.object_id AND fkc.parent_column_id = cp.column_id   
                    WHERE fkc.constraint_object_id = fk.object_id   FOR XML PATH('')   )), 2, 8000)) ParentColumns,   
                    REVERSE(SUBSTRING(REVERSE((   SELECT cr.name + ','   
                    FROM   sys.foreign_key_columns fkc  
                    JOIN sys.columns cr ON fkc.referenced_object_id = cr.object_id AND fkc.referenced_column_id = cr.column_id
                    WHERE fkc.constraint_object_id = fk.object_id   FOR XML PATH('')   )), 2, 8000)) ReferencedColumns   
                    FROM sys.foreign_keys fk    ) a    
                WHERE ParentObject = @TableName    
                */
    
                set @sql=
                '
                use '+@DBName+'
                SELECT distinct '',CONSTRAINT ['' + replace(c.name,@TableName,@NewTableName) + ''] CHECK '' + definition 
                FROM sys.check_constraints c join sys.schemas s on c.schema_id=s.schema_id and s.name=@schema    
                WHERE OBJECT_NAME(parent_object_id) = @TableName
                '
    
                print @sql
                INSERT INTO @Definition(FieldValue) 
                exec sp_executesql @sql,
                                   N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50)',
                           @TableName=@TableName,@NewTableName=@NewTableName,@schema=@schema
                /*
                SELECT ',CONSTRAINT [' + name + '] CHECK ' + definition FROM sys.check_constraints    
                WHERE OBJECT_NAME(parent_object_id) = @TableName
                */
    
                set @sql=
                '
                use '+@DBName+'
                SELECT DISTINCT  PKObject = cco.object_id 
                FROM    sys.key_constraints cco    
                JOIN sys.index_columns cc ON cco.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id    
                JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id
                join sys.schemas s on cco.schema_id=s.schema_id and s.name=@schema
                WHERE    OBJECT_NAME(parent_object_id) = @TableName    AND  i.type = 1 AND    is_primary_key = 1
                '
                print @sql
                INSERT INTO @PKObjectID(ObjectID) 
                exec sp_executesql @sql,
                                   N'@TableName varchar(50),@schema varchar(50)',
                                   @TableName=@TableName,@schema=@schema
                /*
                SELECT DISTINCT  PKObject = cco.object_id 
                FROM    sys.key_constraints cco    
                JOIN sys.index_columns cc ON cco.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id    
                JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id
                WHERE    OBJECT_NAME(parent_object_id) = @TableName    AND  i.type = 1 AND    is_primary_key = 1
                */
    
                set @sql=
                '
                use '+@DBName+'
                SELECT DISTINCT    PKObject = cco.object_id
                FROM    sys.key_constraints cco   
                JOIN sys.index_columns cc ON cco.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id  
                JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id
                join sys.schemas s on cco.schema_id=s.schema_id and s.name=@schema
                WHERE    OBJECT_NAME(parent_object_id) = @TableName AND  i.type = 2 AND    is_primary_key = 0 AND    is_unique_constraint = 1
                '
                print @sql
                INSERT INTO @Uniques(ObjectID)
                exec sp_executesql @sql,
                                   N'@TableName varchar(50),@schema varchar(50)',
                                   @TableName=@TableName,@schema=@schema
                /*
                SELECT DISTINCT    PKObject = cco.object_id
                FROM    sys.key_constraints cco   
                JOIN sys.index_columns cc ON cco.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id  
                JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id
                WHERE    OBJECT_NAME(parent_object_id) = @TableName AND  i.type = 2 AND    is_primary_key = 0 AND    is_unique_constraint = 1
                */
    
                SET @ClusteredPK = CASE WHEN @@ROWCOUNT > 0 THEN 1 ELSE 0 END
    
                declare @t TestTableType
                insert @t select * from @PKObjectID
                declare @u TestTableType
                insert @u select * from @Uniques
    
                set @sql=
                '
                use '+@DBName+'
                SELECT distinct '',CONSTRAINT '' + replace(cco.name,@TableName,@NewTableName) + CASE type WHEN ''PK'' THEN '' PRIMARY KEY '' + CASE WHEN pk.ObjectID IS NULL THEN '' NONCLUSTERED '' ELSE '' CLUSTERED '' END  WHEN ''UQ'' THEN '' UNIQUE '' END + CASE WHEN u.ObjectID IS NOT NULL THEN '' NONCLUSTERED '' ELSE '''' END 
                + ''(''+REVERSE(SUBSTRING(REVERSE(( SELECT   c.name +  + CASE WHEN cc.is_descending_key = 1 THEN '' DESC'' ELSE '' ASC'' END + '',''    
                FROM   sys.key_constraints ccok   
                LEFT JOIN sys.index_columns cc ON ccok.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id
                LEFT JOIN sys.columns c ON cc.object_id = c.object_id AND cc.column_id = c.column_id 
                LEFT JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id  
                WHERE i.object_id = ccok.parent_object_id AND   ccok.object_id = cco.object_id    
                order by key_ordinal FOR XML PATH(''''))), 2, 8000)) + '')''
                FROM sys.key_constraints cco 
                inner join sys.schemas s on cco.schema_id=s.schema_id and s.name=@schema
                LEFT JOIN @U u ON cco.object_id = u.objectID
                LEFT JOIN @t pk ON cco.object_id = pk.ObjectID    
                WHERE    OBJECT_NAME(cco.parent_object_id) = @TableName 
    
                '
    
                print @sql
                INSERT INTO @Definition(FieldValue)
                exec sp_executesql @sql,
                                   N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50),@t TestTableType readonly,@u TestTableType readonly',
                                   @TableName=@TableName,@NewTableName=@NewTableName,@schema=@schema,@t=@t,@u=@u
    
                /*
                SELECT ',CONSTRAINT ' + name + CASE type WHEN 'PK' THEN ' PRIMARY KEY ' + CASE WHEN pk.ObjectID IS NULL THEN ' NONCLUSTERED ' ELSE ' CLUSTERED ' END  WHEN 'UQ' THEN ' UNIQUE ' END + CASE WHEN u.ObjectID IS NOT NULL THEN ' NONCLUSTERED ' ELSE '' END 
                + '(' +REVERSE(SUBSTRING(REVERSE(( SELECT   c.name +  + CASE WHEN cc.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END + ','    
                FROM   sys.key_constraints ccok   
                LEFT JOIN sys.index_columns cc ON ccok.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id
               LEFT JOIN sys.columns c ON cc.object_id = c.object_id AND cc.column_id = c.column_id 
               LEFT JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id  
               WHERE i.object_id = ccok.parent_object_id AND   ccok.object_id = cco.object_id    FOR XML PATH(''))), 2, 8000)) + ')'
               FROM sys.key_constraints cco 
               LEFT JOIN @PKObjectID pk ON cco.object_id = pk.ObjectID    
               LEFT JOIN @Uniques u ON cco.object_id = u.objectID
               WHERE    OBJECT_NAME(cco.parent_object_id) = @TableName 
               */
            END
    
            INSERT INTO @Definition(FieldValue) VALUES(')')
    
            set @sql=
            '
            use '+@DBName+'
            select '' on '' + d.name + ''([''+c.name+''])''
            from sys.tables t join sys.indexes i on(i.object_id = t.object_id and i.index_id < 2)
                              join sys.index_columns ic on(ic.partition_ordinal > 0 and ic.index_id = i.index_id and ic.object_id = t.object_id)
                              join sys.columns c on(c.object_id = ic.object_id and c.column_id = ic.column_id)
                              join sys.schemas s on t.schema_id=s.schema_id
                              join sys.data_spaces d on i.data_space_id=d.data_space_id
            where t.name=@TableName and s.name=@schema
            order by key_ordinal
            '
    
            print 'x'
            print @sql
            INSERT INTO @Definition(FieldValue) 
            exec sp_executesql @sql,
                               N'@TableName varchar(50),@schema varchar(50)',
                               @TableName=@TableName,@schema=@schema
    
            IF @IncludeIndexes = 1
            BEGIN
                set @sql=
                '
                use '+@DBName+'
                SELECT distinct '' CREATE '' + i.type_desc + '' INDEX ['' + replace(i.name COLLATE SQL_Latin1_General_CP1_CI_AS,@TableName,@NewTableName) + ''] ON '+@DBName+'.'+@NewTableSchema+'.'+@NewTableName+' ('' 
                +   REVERSE(SUBSTRING(REVERSE((   SELECT name + CASE WHEN sc.is_descending_key = 1 THEN '' DESC'' ELSE '' ASC'' END + '',''   
                FROM  sys.index_columns sc  
                JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                WHERE  t.name=@TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                                             and is_included_column=0
                ORDER BY key_ordinal ASC   FOR XML PATH('''')    )), 2, 8000)) + '')''+
                ISNULL( '' include (''+REVERSE(SUBSTRING(REVERSE((   SELECT name + '',''   
                FROM  sys.index_columns sc  
                JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                WHERE  t.name=@TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                                             and is_included_column=1
                ORDER BY key_ordinal ASC   FOR XML PATH('''')    )), 2, 8000))+'')'' ,'''')+''''    
                FROM sys.indexes i join sys.tables t on i.object_id=t.object_id
                                   join sys.schemas s on t.schema_id=s.schema_id   
                AND CASE WHEN @ClusteredPK = 1 AND is_primary_key = 1 AND i.type = 1 THEN 0 ELSE 1 END = 1   AND is_unique_constraint = 0   AND is_primary_key = 0 
                    where t.name=@TableName and s.name=@schema
                '
    
                print @sql
                INSERT INTO @Definition(FieldValue)    
                exec sp_executesql @sql,
                                   N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50), @ClusteredPK bit',
                                   @TableName=@TableName,@NewTableName=@NewTableName,@schema=@schema,@ClusteredPK=@ClusteredPK
    
            END 
    
                /*
    
                    SELECT   'CREATE ' + type_desc + ' INDEX [' + [name] COLLATE SQL_Latin1_General_CP1_CI_AS + '] ON [' +  OBJECT_NAME(object_id) + '] (' +   REVERSE(SUBSTRING(REVERSE((   SELECT name + CASE WHEN sc.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END + ','   
                    FROM  sys.index_columns sc  
                    JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                    WHERE  OBJECT_NAME(sc.object_id) = @TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                    ORDER BY index_column_id ASC   FOR XML PATH('')    )), 2, 8000)) + ')'    
                    FROM sys.indexes i    
                    WHERE   OBJECT_NAME(object_id) = @TableName
                    AND CASE WHEN @ClusteredPK = 1 AND is_primary_key = 1 AND type = 1 THEN 0 ELSE 1 END = 1   AND is_unique_constraint = 0   AND is_primary_key = 0 
    
                */
    
                INSERT INTO @MainDefinition(FieldValue)   
                SELECT FieldValue FROM @Definition    
                ORDER BY DefinitionID ASC 
    
                ----------------------------------
    
                declare @q  varchar(max)
    
                set @q=(select replace((SELECT FieldValue FROM @MainDefinition FOR XML PATH('')),'</FieldValue>',''))
    
                set @script=(select REPLACE(@q,'<FieldValue>',''))
                --drop type TestTableType
    END try
    -- ##############################################################################################################################################################################
    BEGIN CATCH        
        BEGIN
            -- INIZIO  Procedura in errore =========================================================================================================================================================
                PRINT '***********************************************************************************************************************************************************' 
                PRINT 'ErrorNumber               : ' + CAST(ERROR_NUMBER() AS NVARCHAR(MAX))
                PRINT 'ErrorSeverity             : ' + CAST(ERROR_SEVERITY() AS NVARCHAR(MAX)) 
                PRINT 'ErrorState                : ' + CAST(ERROR_STATE() AS NVARCHAR(MAX)) 
                PRINT 'ErrorLine                 : ' + CAST(ERROR_LINE() AS NVARCHAR(MAX)) 
                PRINT 'ErrorMessage              : ' + CAST(ERROR_MESSAGE() AS NVARCHAR(MAX))
                PRINT '***********************************************************************************************************************************************************' 
            -- FINE  Procedura in errore =========================================================================================================================================================
        END 
            set @script=''
        return -1
    END CATCH   
    -- ##############################################################################################################################################################################   
    

    执行它:

    declare @s varchar(max)
    exec [util_ScriptTable]   'db','schema_source','table_source',1,1,'schema_dest','tab_dest',0,@s output
    select @s
    
    • 9
  3. LowlyDBA - John M
    2017-10-11T08:06:00+08:002017-10-11T08:06:00+08:00

    This might be using a jackhammer to put a nail in a wall, but given the broadness of the question I think it is a valid option to mention.

    If you're using SQL Server 2012 SP4+, 2014 SP2+ or 2016 SP1+, you can leverage DBCC CLONEDATABASE to create a schema-only copy of your database sans data. This is ideal for generating comprehensive schema copies of multiple tables and may alleviate the need to "automate" the process of looping through a series of tables, but be warned that all of the table copies will be created inside of a new read-only database.

    These tables will include foreign keys, primary keys, indexes, and constraints. They will also include statistics and query store data (unless you specify NO_STATISTICS and NO_QUERYSTORE).

    The syntax is

    DBCC CLONEDATABASE (source_database_name, target_database_name)[WITH [NO_STATISTICS][,NO_QUERYSTORE]] 
    

    还有其他一些注意事项需要注意,Brent Ozar 有一篇很棒的帖子,但这一切都归结为您要如何以及为什么要创建表格副本,以及任何细微之处是否会破坏交易.

    • 5
  4. Martin
    2017-10-11T07:43:16+08:002017-10-11T07:43:16+08:00

    You can use the "Generate script" command in SQL Server Management Studio to get a script that can create your table, including indexes, triggers, foreign keys, etc.

    In SSMS

    • Right-click on the database the table is in
    • Choose Tasks -> Generate scripts
    • Choose "Select specific database objects"
    • Expand the "Tables" list, and check the checkbox next to the table you want to script
    • Click "Next" to go to the next page of the wizard
    • Set the save options as you want them, then click the "Advanced" button
    • Set the advanced options as you want them. In particular, under "Table/View Options", note that (by default) indexes, triggers, and full-text indexes are not scripted; if you want those, switch them from "False" to "True"
    • When done, click "OK" to save your advanced options, and "Next" to review your selections. Click "Next" again to actually generate the script.

    You can then edit to include just what you need in your destination database.

    • 4
  5. Brent Willis
    2019-09-20T11:16:29+08:002019-09-20T11:16:29+08:00

    这是基于此线程中 E.Mantovanelli 的版本的版本。这更正了唯一索引在生成的脚本中不包含关键字 UNIQUE 的问题。它还添加了参数,因此可以在没有非聚集索引的情况下创建表,或者您只能编写非聚集索引的脚本。我用它来创建一个阶段表,加载它添加非聚集索引然后进行表切换,这允许加载运行得更快并且索引不会碎片化。

    SET ANSI_NULLS ON;
    GO
    
    SET QUOTED_IDENTIFIER ON;
    GO
    
    --*************************************************************************************************'
    --    La procedura crea lo script di una tabella
    --    Tabella   : xxxxx
    --    Creata da : E.Mantovanelli
    --    Data creazione : 28-06-2012
    --    Data modifica: 28-06-2012
    --*************************************************************************************************'
    
    /*
        --      ID----|-----Data-----|--    User        ---------   | ----  Note
                            20-11-2013      E.Mantovanelli                  distinzione schema delle tabelle
                                                                            estrazione da db selezionato
                                                                            aggiunta estrazione partizione
    */
    --*************************************************************************************************'
    --    Creates a copy of a table with optionally all indexes and constraints depending on parameters
    --    Updated by : Brent Willis
    --    Date Updated : 09-11-2019
    --    Changes: Added the ability to create a table with clustered index and constraints only or to 
    --             CREATE just the non-clustered indexes. This is helpful so a table can be created, 
    --             loaded then non-clusted indexes added so it can them be swapped into a partitioned 
    --             table with freshly created indexes to lower fragmentation. 
    --
    --             Also fixed an issue when a unique index was defined the index resulting table was not unique. 
    --*************************************************************************************************'
    
    ALTER PROCEDURE dbo.util_ScriptTable
        @DBName                sysname
      , @schema                sysname
      , @TableName             sysname
      , @includeTable          Bit     = 1
      , @IncludeConstraints    Bit     = 1
      , @IncludeClusteredIndex Bit     = 1
      , @IncludeIndexes        Bit     = 1
      , @NewTableSchema        sysname
      , @NewTableName          sysname = NULL
      , @UseSystemDataTypes    Bit     = 0
      , @script                Varchar(MAX) OUTPUT
    AS
        BEGIN TRY
            IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'TestTableType')
                CREATE TYPE TestTableType AS TABLE (ObjectID Int); --drop type TestTableType
    
            DECLARE @sql NVarchar(MAX);
    
            DECLARE @MainDefinition Table (FieldValue Varchar(200));
    
            --DECLARE @DBName SYSNAME
            DECLARE @ClusteredPK Bit;
            DECLARE @TableSchema NVarchar(255);
    
            --SET @DBName = DB_NAME(DB_ID())
            SELECT @TableName = name FROM sys.sysobjects WHERE id = Object_Id(@TableName);
    
            DECLARE @ShowFields Table (FieldID            Int IDENTITY(1, 1)
                                     , DatabaseName       Varchar(100)
                                     , TableOwner         Varchar(100)
                                     , TableName          Varchar(100)
                                     , FieldName          Varchar(100)
                                     , ColumnPosition     Int
                                     , ColumnDefaultValue Varchar(100)
                                     , ColumnDefaultName  Varchar(100)
                                     , IsNullable         Bit
                                     , DataType           Varchar(100)
                                     , MaxLength          Varchar(10)
                                     , NumericPrecision   Int
                                     , NumericScale       Int
                                     , DomainName         Varchar(100)
                                     , FieldListingName   Varchar(110)
                                     , FieldDefinition    Char(1)
                                     , IdentityColumn     Bit
                                     , IdentitySeed       Int
                                     , IdentityIncrement  Int
                                     , IsCharColumn       Bit
                                     , IsComputed         Varchar(255));
    
            DECLARE @HoldingArea Table (FldID SmallInt IDENTITY(1, 1), Flds Varchar(4000), FldValue Char(1) DEFAULT (0));
    
            DECLARE @PKObjectID Table (ObjectID Int);
    
            DECLARE @Uniques Table (ObjectID Int);
    
            DECLARE @Definition Table (DefinitionID SmallInt IDENTITY(1, 1), FieldValue Varchar(2000));
    
            SET @sql = N'
      use ' + @DBName + N'
      SELECT distinct DB_NAME()
                ,TABLE_SCHEMA
                ,TABLE_NAME
                ,''[''+COLUMN_NAME+'']'' as COLUMN_NAME
                ,CAST(ORDINAL_POSITION AS INT)
                ,COLUMN_DEFAULT
                ,dobj.name AS ColumnDefaultName
                ,CASE WHEN c.IS_NULLABLE = ''YES'' THEN 1 ELSE 0 END
                ,DATA_TYPE
                ,case CHARACTER_MAXIMUM_LENGTH when -1 then ''max'' else CAST(CHARACTER_MAXIMUM_LENGTH AS varchar) end--CAST(CHARACTER_MAXIMUM_LENGTH AS INT)
                ,CAST(NUMERIC_PRECISION AS INT)
                ,CAST(NUMERIC_SCALE AS INT)
                ,DOMAIN_NAME
                ,COLUMN_NAME + '',''
                ,'''' AS FieldDefinition
                ,CASE WHEN ic.object_id IS NULL THEN 0 ELSE 1 END AS IdentityColumn
                ,CAST(ISNULL(ic.seed_value,0) AS INT) AS IdentitySeed
                ,CAST(ISNULL(ic.increment_value,0) AS INT) AS IdentityIncrement
                ,CASE WHEN st.collation_name IS NOT NULL THEN 1 ELSE 0 END AS IsCharColumn 
                ,cc.definition 
                FROM INFORMATION_SCHEMA.COLUMNS c
                JOIN sys.columns sc ON  c.TABLE_NAME = OBJECT_NAME(sc.object_id) AND c.COLUMN_NAME = sc.Name
                LEFT JOIN sys.identity_columns ic ON c.TABLE_NAME = OBJECT_NAME(ic.object_id) AND c.COLUMN_NAME = ic.Name
                JOIN sys.types st ON COALESCE(c.DOMAIN_NAME,c.DATA_TYPE) = st.name
                LEFT OUTER JOIN sys.objects dobj ON dobj.object_id = sc.default_object_id AND dobj.type = ''D''
                left join sys.computed_columns cc on c.TABLE_NAME=OBJECT_NAME(cc.object_id) and sc.column_id=cc.column_id
        WHERE c.TABLE_NAME = @TableName and c.TABLE_SCHEMA=@schema 
        ORDER BY c.TABLE_NAME, c.ORDINAL_POSITION
        '   ;
    
            --PRINT @sql;
            INSERT INTO @ShowFields (DatabaseName
                                   , TableOwner
                                   , TableName
                                   , FieldName
                                   , ColumnPosition
                                   , ColumnDefaultValue
                                   , ColumnDefaultName
                                   , IsNullable
                                   , DataType
                                   , MaxLength
                                   , NumericPrecision
                                   , NumericScale
                                   , DomainName
                                   , FieldListingName
                                   , FieldDefinition
                                   , IdentityColumn
                                   , IdentitySeed
                                   , IdentityIncrement
                                   , IsCharColumn
                                   , IsComputed)
            EXEC sys.sp_executesql @sql
                                 , N'@TableName varchar(50),@schema varchar(50)'
                                 , @TableName = @TableName
                                 , @schema = @schema;
    
            SELECT TOP 1 @TableSchema = TableOwner FROM @ShowFields;
    
            INSERT INTO @HoldingArea (Flds) VALUES ('(');
    
            IF @includeTable = 1
                BEGIN
                    INSERT INTO @Definition (FieldValue)
                    VALUES
                    (   'CREATE TABLE ' + CASE
                                              WHEN @NewTableName IS NOT NULL THEN
                                                  @DBName + '.' + @NewTableSchema + '.' + @NewTableName
                                              ELSE
                                                  @DBName + '.' + @TableSchema + '.' + @TableName
                                          END);
    
                    INSERT INTO @Definition (FieldValue) VALUES ('(');
    
                    INSERT INTO @Definition (FieldValue)
                    SELECT Char(10) + FieldName + ' '
                           + CASE
                                 WHEN DomainName IS NOT NULL AND @UseSystemDataTypes = 0 THEN
                                     DomainName + CASE WHEN IsNullable = 1 THEN ' NULL ' ELSE ' NOT NULL ' END
                                 ELSE
                                     CASE
                                         WHEN IsComputed IS NULL THEN
                                             Upper(DataType)
                                             + CASE
                                                   WHEN IsCharColumn = 1 THEN
                                                       '(' + Cast(MaxLength AS Varchar(10)) + ')'
                                                   ELSE
                                                       CASE
                                                           WHEN DataType = 'numeric' THEN
                                                               '(' + Cast(NumericPrecision AS Varchar(10)) + ','
                                                               + Cast(NumericScale AS Varchar(10)) + ')'
                                                           ELSE
                                                               CASE
                                                                   WHEN DataType = 'decimal' THEN
                                                                       '(' + Cast(NumericPrecision AS Varchar(10)) + ','
                                                                       + Cast(NumericScale AS Varchar(10)) + ')'
                                                                   ELSE
                                                                       ''
                                                               END
                                                       END
                                               END
                                             + CASE
                                                   WHEN IdentityColumn = 1 THEN
                                                       ' IDENTITY(' + Cast(IdentitySeed AS Varchar(5)) + ','
                                                       + Cast(IdentityIncrement AS Varchar(5)) + ')'
                                                   ELSE
                                                       ''
                                               END + CASE WHEN IsNullable = 1 THEN ' NULL ' ELSE ' NOT NULL ' END
                                             + CASE
                                                   WHEN ColumnDefaultName IS NOT NULL AND @IncludeConstraints = 1 THEN
                                                       'CONSTRAINT ['
                                                       + Replace(ColumnDefaultName, @TableName, @NewTableName)
                                                       + '] DEFAULT' + Upper(ColumnDefaultValue)
                                                   ELSE
                                                       ''
                                               END
                                         ELSE
                                             ' as ' + IsComputed + ' '
                                     END
                             END + CASE
                                       WHEN FieldID = (SELECT Max(FieldID)FROM @ShowFields) THEN
                                           ''
                                       ELSE
                                           ','
                                   END
                    FROM @ShowFields;
    
                    --------------------------------------------------
                    IF @IncludeConstraints = 1
                        BEGIN
                            SET @sql = N'
            use ' +         @DBName + N'
            SELECT  distinct  '',CONSTRAINT ['' + replace(name,@TableName,@NewTableName) + ''] FOREIGN KEY ('' + ParentColumns + '') REFERENCES ['' + ReferencedObject + '']('' + ReferencedColumns + '')'' 
               FROM ( SELECT   ReferencedObject = OBJECT_NAME(fk.referenced_object_id), ParentObject = OBJECT_NAME(parent_object_id),fk.name
                    ,   REVERSE(SUBSTRING(REVERSE((   SELECT cp.name + '',''   
                    FROM   sys.foreign_key_columns fkc   
                    JOIN sys.columns cp ON fkc.parent_object_id = cp.object_id AND fkc.parent_column_id = cp.column_id   
                    WHERE fkc.constraint_object_id = fk.object_id   FOR XML PATH('''')   )), 2, 8000)) ParentColumns,   
                    REVERSE(SUBSTRING(REVERSE((   SELECT cr.name + '',''   
                    FROM   sys.foreign_key_columns fkc  
                    JOIN sys.columns cr ON fkc.referenced_object_id = cr.object_id AND fkc.referenced_column_id = cr.column_id
                    WHERE fkc.constraint_object_id = fk.object_id   FOR XML PATH('''')   )), 2, 8000)) ReferencedColumns   
                    FROM sys.foreign_keys fk    
                        inner join sys.schemas s on fk.schema_id=s.schema_id and s.name=@schema) a    
                WHERE ParentObject = @TableName    
            '               ;
    
                            --PRINT @sql;
                            INSERT INTO @Definition (FieldValue)
                            EXEC sys.sp_executesql @sql
                                                 , N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50)'
                                                 , @TableName = @TableName
                                                 , @NewTableName = @NewTableName
                                                 , @schema = @schema;
    
                            SET @sql = N'
                use ' +     @DBName + N'
                SELECT distinct '',CONSTRAINT ['' + replace(c.name,@TableName,@NewTableName) + ''] CHECK '' + definition 
                FROM sys.check_constraints c join sys.schemas s on c.schema_id=s.schema_id and s.name=@schema    
                WHERE OBJECT_NAME(parent_object_id) = @TableName
                '           ;
    
                            --PRINT @sql;
                            INSERT INTO @Definition (FieldValue)
                            EXEC sys.sp_executesql @sql
                                                 , N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50)'
                                                 , @TableName = @TableName
                                                 , @NewTableName = @NewTableName
                                                 , @schema = @schema;
    
                            SET @sql = N'
                use ' +     @DBName + N'
                SELECT DISTINCT  PKObject = cco.object_id 
                FROM    sys.key_constraints cco    
                JOIN sys.index_columns cc ON cco.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id    
                JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id
                join sys.schemas s on cco.schema_id=s.schema_id and s.name=@schema
                WHERE    OBJECT_NAME(parent_object_id) = @TableName    AND  i.type = 1 AND    is_primary_key = 1
                '           ;
    
                            --PRINT @sql;
                            INSERT INTO @PKObjectID (ObjectID)
                            EXEC sys.sp_executesql @sql
                                                 , N'@TableName varchar(50),@schema varchar(50)'
                                                 , @TableName = @TableName
                                                 , @schema = @schema;
    
                            SET @sql = N'
                use ' +     @DBName + N'
                SELECT DISTINCT    PKObject = cco.object_id
                FROM    sys.key_constraints cco   
                JOIN sys.index_columns cc ON cco.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id  
                JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id
                join sys.schemas s on cco.schema_id=s.schema_id and s.name=@schema
                WHERE    OBJECT_NAME(parent_object_id) = @TableName AND  i.type = 2 AND    is_primary_key = 0 AND    is_unique_constraint = 1
                '           ;
    
                            --PRINT @sql;
                            INSERT INTO @Uniques (ObjectID)
                            EXEC sys.sp_executesql @sql
                                                 , N'@TableName varchar(50),@schema varchar(50)'
                                                 , @TableName = @TableName
                                                 , @schema = @schema;
    
                            SET @ClusteredPK = CASE WHEN @@ROWCOUNT > 0 THEN 1 ELSE 0 END;
    
                            DECLARE @t TestTableType;
    
                            INSERT @t SELECT * FROM @PKObjectID;
    
                            DECLARE @u TestTableType;
    
                            INSERT @u SELECT * FROM @Uniques;
    
                            SET @sql = N'
                use ' +     @DBName + N'
                SELECT distinct '',CONSTRAINT '' + replace(cco.name,@TableName,@NewTableName) + CASE type WHEN ''PK'' THEN '' PRIMARY KEY '' + CASE WHEN pk.ObjectID IS NULL THEN '' NONCLUSTERED '' ELSE '' CLUSTERED '' END  WHEN ''UQ'' THEN '' UNIQUE '' END + CASE WHEN u.ObjectID IS NOT NULL THEN '' NONCLUSTERED '' ELSE '''' END 
                + ''(''+REVERSE(SUBSTRING(REVERSE(( SELECT   c.name +  + CASE WHEN cc.is_descending_key = 1 THEN '' DESC'' ELSE '' ASC'' END + '',''    
                FROM   sys.key_constraints ccok   
                LEFT JOIN sys.index_columns cc ON ccok.parent_object_id = cc.object_id AND cco.unique_index_id = cc.index_id
                LEFT JOIN sys.columns c ON cc.object_id = c.object_id AND cc.column_id = c.column_id 
                LEFT JOIN sys.indexes i ON cc.object_id = i.object_id AND cc.index_id = i.index_id  
                WHERE i.object_id = ccok.parent_object_id AND   ccok.object_id = cco.object_id    
                order by key_ordinal FOR XML PATH(''''))), 2, 8000)) + '')''
                FROM sys.key_constraints cco 
                inner join sys.schemas s on cco.schema_id=s.schema_id and s.name=@schema
                LEFT JOIN @U u ON cco.object_id = u.objectID
                LEFT JOIN @t pk ON cco.object_id = pk.ObjectID    
                WHERE    OBJECT_NAME(cco.parent_object_id) = @TableName 
    
                '           ;
    
                            --PRINT @sql;
                            INSERT INTO @Definition (FieldValue)
                            EXEC sys.sp_executesql @sql
                                                 , N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50),@t TestTableType readonly,@u TestTableType readonly'
                                                 , @TableName = @TableName
                                                 , @NewTableName = @NewTableName
                                                 , @schema = @schema
                                                 , @t = @t
                                                 , @u = @u;
                        END;
    
                    INSERT INTO @Definition (FieldValue) VALUES (')');
                END;
    
            SET @sql = N'
            use ' + @DBName
                       + N'
            select '' on '' + d.name + ''([''+c.name+''])''
            from sys.tables t join sys.indexes i on(i.object_id = t.object_id and i.index_id < 2)
                              join sys.index_columns ic on(ic.partition_ordinal > 0 and ic.index_id = i.index_id and ic.object_id = t.object_id)
                              join sys.columns c on(c.object_id = ic.object_id and c.column_id = ic.column_id)
                              join sys.schemas s on t.schema_id=s.schema_id
                              join sys.data_spaces d on i.data_space_id=d.data_space_id
            where t.name=@TableName and s.name=@schema
            order by key_ordinal
            ';
    
            PRINT 'x';
    
            --PRINT @sql;
            INSERT INTO @Definition (FieldValue)
            EXEC sys.sp_executesql @sql
                                 , N'@TableName varchar(50),@schema varchar(50)'
                                 , @TableName = @TableName
                                 , @schema = @schema;
    
            IF @IncludeClusteredIndex = 1
                BEGIN
                    SET @sql = N'
                use ' + @DBName
                               + N'
                SELECT distinct '' CREATE '' + CASE WHEN i.is_unique = 1 THEN ''UNIQUE '' ELSE '''' end + i.type_desc + '' INDEX ['' + replace(i.name COLLATE SQL_Latin1_General_CP1_CI_AS,@TableName,@NewTableName) + ''] ON '
                               + @DBName + N'.' + @NewTableSchema + N'.' + @NewTableName
                               + N' ('' 
                +   REVERSE(SUBSTRING(REVERSE((   SELECT name + CASE WHEN sc.is_descending_key = 1 THEN '' DESC'' ELSE '' ASC'' END + '',''   
                FROM  sys.index_columns sc  
                JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                WHERE  t.name=@TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                                             and is_included_column=0
                ORDER BY key_ordinal ASC   FOR XML PATH('''')    )), 2, 8000)) + '')''+
                ISNULL( '' include (''+REVERSE(SUBSTRING(REVERSE((   SELECT name + '',''   
                FROM  sys.index_columns sc  
                JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                WHERE  t.name=@TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                                             and is_included_column=1 
                ORDER BY key_ordinal ASC   FOR XML PATH('''')    )), 2, 8000))+'')'' ,'''')+''''    
                FROM sys.indexes i join sys.tables t on i.object_id=t.object_id
                                   join sys.schemas s on t.schema_id=s.schema_id   
                AND CASE WHEN @ClusteredPK = 1 AND is_primary_key = 1 AND i.type = 1 THEN 0 ELSE 1 END = 1   AND is_unique_constraint = 0   AND is_primary_key = 0 
                    where t.name=@TableName and s.name=@schema and i.type_desc = ''CLUSTERED''
                '   ;
    
                    --PRINT @sql;
                    INSERT INTO @Definition (FieldValue)
                    EXEC sys.sp_executesql @sql
                                         , N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50), @ClusteredPK bit'
                                         , @TableName = @TableName
                                         , @NewTableName = @NewTableName
                                         , @schema = @schema
                                         , @ClusteredPK = @ClusteredPK;
                END;
    
            IF @IncludeIndexes = 1
                BEGIN
                    SET @sql = N'
                use ' + @DBName
                               + N'
                SELECT distinct '' CREATE '' + CASE WHEN i.is_unique = 1 THEN ''UNIQUE '' ELSE '''' end + i.type_desc + '' INDEX ['' + replace(i.name COLLATE SQL_Latin1_General_CP1_CI_AS,@TableName,@NewTableName) + ''] ON '
                               + @DBName + N'.' + @NewTableSchema + N'.' + @NewTableName
                               + N' ('' 
                +   REVERSE(SUBSTRING(REVERSE((   SELECT name + CASE WHEN sc.is_descending_key = 1 THEN '' DESC'' ELSE '' ASC'' END + '',''   
                FROM  sys.index_columns sc  
                JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                WHERE  t.name=@TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                                             and is_included_column=0
                ORDER BY key_ordinal ASC   FOR XML PATH('''')    )), 2, 8000)) + '')''+
                ISNULL( '' include (''+REVERSE(SUBSTRING(REVERSE((   SELECT name + '',''   
                FROM  sys.index_columns sc  
                JOIN sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id   
                WHERE  t.name=@TableName AND  sc.object_id = i.object_id AND  sc.index_id = i.index_id   
                                             and is_included_column=1 
                ORDER BY key_ordinal ASC   FOR XML PATH('''')    )), 2, 8000))+'')'' ,'''')+''''    
                FROM sys.indexes i join sys.tables t on i.object_id=t.object_id
                                   join sys.schemas s on t.schema_id=s.schema_id   
                AND CASE WHEN @ClusteredPK = 1 AND is_primary_key = 1 AND i.type = 1 THEN 0 ELSE 1 END = 1   AND is_unique_constraint = 0   AND is_primary_key = 0 
                    where t.name=@TableName and s.name=@schema and i.type_desc <> ''CLUSTERED''
                '   ;
    
                    PRINT @sql;
    
                    INSERT INTO @Definition (FieldValue)
                    EXEC sys.sp_executesql @sql
                                         , N'@TableName varchar(50),@NewTableName varchar(50),@schema varchar(50), @ClusteredPK bit'
                                         , @TableName = @TableName
                                         , @NewTableName = @NewTableName
                                         , @schema = @schema
                                         , @ClusteredPK = @ClusteredPK;
                END;
    
            --SELECT * FROM @Definition;
            INSERT INTO @MainDefinition (FieldValue)
            SELECT FieldValue FROM @Definition ORDER BY DefinitionID ASC;
    
            --SELECT * FROM @MainDefinition;
    
            ----------------------------------
            DECLARE @q Varchar(MAX);
    
            SET @q = (SELECT Replace((SELECT FieldValue FROM @MainDefinition FOR XML PATH('')), '</FieldValue>', ''));
            SET @script = (SELECT Replace(@q, '<FieldValue>', ''));
        END TRY
        -- ##############################################################################################################################################################################
        BEGIN CATCH
            BEGIN
                -- INIZIO  Procedura in errore =========================================================================================================================================================
                PRINT '***********************************************************************************************************************************************************';
                PRINT 'ErrorNumber               : ' + Cast(Error_Number() AS NVarchar(MAX));
                PRINT 'ErrorSeverity             : ' + Cast(Error_Severity() AS NVarchar(MAX));
                PRINT 'ErrorState                : ' + Cast(Error_State() AS NVarchar(MAX));
                PRINT 'ErrorLine                 : ' + Cast(Error_Line() AS NVarchar(MAX));
                PRINT 'ErrorMessage              : ' + Cast(Error_Message() AS NVarchar(MAX));
                PRINT '***********************************************************************************************************************************************************';
            -- FINE  Procedura in errore =========================================================================================================================================================
            END;
    
            SET @script = '';
    
            RETURN -1;
        END CATCH;
    -- ##############################################################################################################################################################################   
    
    • 1
  6. HansM
    2016-03-10T10:07:35+08:002016-03-10T10:07:35+08:00

    You could use this script to copy a table structure with foreign keys but without indexes. This script handles user defined types and computed columns gracefully.

    --\
    ---) Author: Hans Michiels
    ---) Script to copy a sql server table structure with foreign keys but without indexes.
    ---) This script handles user defined types and computed columns gracefully.
    --/
    /*
    (c) Copyright 2016 - hansmichiels.com
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
    */
    
    --\
    ---) VARIABLES DECLARATIONS
    --/
    DECLARE @CrLf NVARCHAR(2) 
    DECLARE @Indent NVARCHAR(2) 
    DECLARE @nsql NVARCHAR(MAX)
    DECLARE @SimulationMode CHAR(1) 
    DECLARE @SourceSchemaAndTable NVARCHAR(260) 
    DECLARE @TargetSchemaAndTable NVARCHAR(260) 
    DECLARE @FkNameSuffix NVARCHAR(128)
    DECLARE @TableOptions NVARCHAR(500)
    
    --\
    ---) CONFIGURATION: set the source and target schema/tablename here, and some other settings.
    --/
    SELECT 
        @SimulationMode = 'Y' -- Use Y if you only want the SQL statement in the output window without it being executed.
      , @SourceSchemaAndTable = '[Production].[Product]'
      , @TargetSchemaAndTable = '[stg].[Product]'
      , @TableOptions = ' WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]'
      , @FkNameSuffix = '_' + REPLACE(CAST(NEWID() AS VARCHAR(40)), '-', '') -- A Guid is added to the foreign key name to make it unique.
      , @CrLf = CHAR(13) + CHAR(10)
      , @Indent = SPACE(2)
      -- For 'min' script use this (in case sql is near 4000 characters):
      -- , @CrLf  = ' '
      -- , @Indent = ''
    
    --\
    ---) BUILD SQL FOR CLONING TABLE
    --/
    SELECT @nsql
        = ISNULL(@nsql, '')
        + CASE col_sequence WHEN 1 THEN
          @CrLf + 'IF OBJECT_ID(N''' + @TargetSchemaAndTable + ''', ''U'') IS NOT NULL DROP TABLE ' + @TargetSchemaAndTable + ';'
        + @CrLf + 'CREATE TABLE ' + @TargetSchemaAndTable + @CrLf + @Indent + '( ' ELSE @CrLf + @Indent + ', ' END
        + [definition]
    FROM (
          SELECT ROW_NUMBER() OVER (PARTITION BY tb.object_id ORDER BY tb.object_id, col.column_id) AS col_sequence
            , QUOTENAME(col.name) + ' '
            + COALESCE(
                'AS ' + cmp.definition + CASE ISNULL(cmp.is_persisted, 0) WHEN 1 THEN ' PERSISTED ' ELSE '' END,
                CASE
                  WHEN col.system_type_id != col.user_type_id THEN QUOTENAME(usr_tp.schema_name) + '.' + QUOTENAME(usr_tp.name)
                  ELSE
                    QUOTENAME(sys_tp.name) +
                    CASE
                      WHEN sys_tp.name IN ('char', 'varchar', 'binary', 'varbinary') THEN '(' + CONVERT(VARCHAR, CASE col.max_length WHEN -1 THEN 'max' ELSE CAST(col.max_length AS varchar(10)) END) + ')'
                      WHEN sys_tp.name IN ('nchar', 'nvarchar') THEN '(' + CONVERT(VARCHAR, CASE col.max_length WHEN -1 THEN 'max' ELSE CAST(col.max_length/2 AS varchar(10)) END) + ')'
                      WHEN sys_tp.name IN ('decimal', 'numeric') THEN '(' + CAST(col.precision AS VARCHAR) + ',' + CAST(col.scale AS VARCHAR) +  ')'
                      WHEN sys_tp.name IN ('datetime2') THEN '(' + CAST(col.scale AS VARCHAR) +  ')'
                      ELSE ''
                    END          
                END
                )       
            + CASE col.is_nullable
                WHEN 0 THEN ' NOT'
                ELSE ''
              END + ' NULL' AS [definition]
            FROM sys.tables tb
            JOIN sys.schemas sch
              ON sch.schema_id = tb.schema_id
            JOIN sys.columns col
              ON col.object_id = tb.object_id
            JOIN sys.types sys_tp
              ON col.system_type_id = sys_tp.system_type_id
            AND col.system_type_id = sys_tp.user_type_id
            LEFT JOIN
                (
                SELECT tp.*, sch.name AS [schema_name]
                FROM sys.types tp
                JOIN sys.schemas sch
                ON tp.schema_id = sch.schema_id
                ) usr_tp
              ON col.system_type_id = usr_tp.system_type_id
            AND col.user_type_id = usr_tp.user_type_id
            LEFT JOIN sys.computed_columns cmp
              ON cmp.object_id = tb.object_id
            AND cmp.column_id = col.column_id
          WHERE tb.object_id = OBJECT_ID(@SourceSchemaAndTable, 'U')
          ) subqry
    ;
    SELECT @nsql
        = ISNULL(@nsql, '')
        + CASE col_sequence
            WHEN 1 THEN @CrLf + ', PRIMARY KEY ' + CASE is_clustered_index WHEN 1 THEN 'CLUSTERED' ELSE 'NONCLUSTERED' END
                + @CrLf + @Indent + '( '
            ELSE @CrLf + @Indent + ', '
          END
        + QUOTENAME(pk_cols.column_name)
        + CASE is_descending_key
            WHEN 1 THEN ' DESC'
            ELSE ' ASC'
          END
    FROM (
          SELECT TOP 2147483647 sch.name as schema_name, tb.name as table_name, col.name as column_name
                    , ROW_NUMBER() OVER (PARTITION BY tb.object_id ORDER BY tb.object_id, col.column_id) AS col_sequence
                    , ic.is_descending_key
                    , CASE WHEN idx.index_id = 1 THEN 1 ELSE 0 END AS [is_clustered_index]
            FROM sys.tables tb
            JOIN sys.schemas sch
              ON sch.schema_id = tb.schema_id
            JOIN sys.indexes idx
              ON idx.is_primary_key = 1
            AND idx.object_id = tb.object_id
            JOIN sys.index_columns ic
              ON is_included_column = 0  
            AND ic.object_id = tb.object_id
            AND ic.index_id = idx.index_id
            JOIN sys.columns col
              ON col.column_id = ic.column_id
            AND col.object_id = tb.object_id
          WHERE tb.object_id = OBJECT_ID(@SourceSchemaAndTable, 'U')
          ORDER BY col.column_id
          ) pk_cols
    
    SELECT @nsql = @nsql + @CrLf + @indent + ') ' + @TableOptions
    
    IF @SimulationMode = 'Y' 
    BEGIN
      PRINT '-- Simulation mode: script is not executed.'
    END
    PRINT @nsql;
    IF @SimulationMode != 'Y' 
    BEGIN
      EXEC(@nsql);
    END
    
    --\
    ---) Copy foreign key constraints
    ---) A guid is added to the foreign key name to make it unique within the database.
    --/
    SET @nsql = N'';
    SELECT @nsql += N'
    ALTER TABLE '
          + @TargetSchemaAndTable
          + ' ADD CONSTRAINT [' + LEFT(fk.name + @FkNameSuffix, 128) +  '] '
          + ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(col.name)
          -- get all the columns in the constraint table
          FROM sys.columns AS col
          JOIN sys.foreign_key_columns AS fkc
            ON fkc.parent_column_id = col.column_id
            AND fkc.parent_object_id = col.[object_id]
          WHERE fkc.constraint_object_id = fk.[object_id]
          ORDER BY fkc.constraint_column_id
          FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'')
          + ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rtb.name)
          + '('
          + STUFF((SELECT ',' + QUOTENAME(col.name)
          -- get all the referenced columns
          FROM sys.columns AS col
          JOIN sys.foreign_key_columns AS fkc
            ON fkc.referenced_column_id = col.column_id
            AND fkc.referenced_object_id = col.[object_id]
          WHERE fkc.constraint_object_id = fk.object_id
          ORDER BY fkc.constraint_column_id
          FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
    FROM sys.foreign_keys AS fk
    JOIN sys.tables AS rtb -- referenced table
        ON fk.referenced_object_id = rtb.[object_id]
    JOIN sys.schemas AS rs
        ON rtb.[schema_id] = rs.[schema_id]
    JOIN sys.tables AS ctb -- constraint table
        ON fk.parent_object_id = ctb.[object_id]
    WHERE rtb.is_ms_shipped = 0 AND ctb.is_ms_shipped = 0
      AND ctb.object_id = OBJECT_ID(@SourceSchemaAndTable, 'U');
    
    IF @SimulationMode = 'Y' 
    BEGIN
      PRINT '-- Simulation mode: script is not executed.'
    END
    PRINT @nsql;
    IF @SimulationMode != 'Y' 
    BEGIN
      EXEC(@nsql);
    END
    

    If you are interested you can find it also on my blog: http://www.hansmichiels.com/2016/02/18/how-to-copy-a-database-table-structure-t-sql-scripting-series-s01e01/

    • 0
  7. S Ahmed
    2014-05-29T09:32:28+08:002014-05-29T09:32:28+08:00
    Select *
    into [new table name]
    from [table to be copied name]
    where 0=1
    
    • -3

相关问题

  • 死锁的主要原因是什么,可以预防吗?

  • 我在索引上放了多少“填充”?

  • 如何确定是否需要或需要索引

  • RDBMS 上的“索引”是什么意思?[关闭]

  • 如何在 MySQL 中创建条件索引?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve