最简单的方法是复制SQL Server DB来测试数据库?

时间:2010-04-20 16:16:16

标签: sql-server database sql-server-2008

获取SQL Server数据库并对其进行测试副本的最简单方法是什么?

我查看了一些现有主题,但不确定是否有更简单的方法。我有数据库发布者。我希望能够将两个数据库保存在同一台服务器上。

更新:我使用Microsoft SQL Server发布向导来脚本化文件,创建新数据库,添加“use db”并执行脚本。这似乎工作正常。建议不要使用附加/分离,因为如果它是全文搜索数据库或缺少日志,它会将链接留回原始位置。

4 个答案:

答案 0 :(得分:6)

我总是只备份它然后恢复到不同的名称/文件集; How to: Restore a Database to a New Location and Name (Transact-SQL) 或者你可以创建一个空的db&使用恢复“向导”启用OVERWRITE并更改恢复文件路径。

答案 1 :(得分:2)

我只是创建数据库,然后使用SS Mgmt Studio中的“导入数据”任务来复制数据。或者,您可以备份生产数据库并将其还原到测试数据库中。

也许不是绝对最简单的方式,但相当低的戏剧性。您还可以将数据编写到文件中并将其重新播放到新数据库中 - 这需要一段时间,但它对于版本控制之类的东西很方便,而且它是人类(好的,“开发人员”) - 可读。

答案 2 :(得分:1)

取出数据库(意味着将其脱机),复制mdf文件,然后重新附加原始数据和副本。

答案 3 :(得分:0)

我经常拥有具有完全相同架构的Test和Live数据库。它们通常具有随我的开发更改状态而更改的存储过程。因此,我不能总是仅备份和还原。我写了一个查询,该查询遍历数据库中的所有表,删除了数据。然后再次循环并从实时数据库插入。 在下面,我的测试数据库称为WorkflowTest,而我的实时数据库称为Workflow,但是您只需在变量中替换数据库名称即可。只需确保连接到TEST数据库即可。

但是表名和列完全是任意的。 我多次循环,因为我不想担心外键约束。某些删除/插入操作将失败,因为它希望数据存在于另一个表中。

我发现我的全部45张左右的桌子在大约2-3个循环中被完全填充。

在插入循环中,它首先尝试通过打开IDENTITY_INSERT来检查表是否具有标识列。如果这没有失败,那么它将构建一个插入语句,其中前面的IDENTITY_INSERT为开,随后的IDENTITY_INSERT为关。必须在同一EXEC语句中完成此操作,因为EXEC中的命令在执行后会超出范围。

事后看来,我想我可以将所有测试存储过程脚本化为alter语句,从活动数据库的备份中恢复测试数据库,然后执行我的alter语句。但是我发现用户安全设置无法正确还原,因此有时也可能很麻烦。

            -- Gets a list of all tables in the Test database
            -- first loops through them and deletes all records.
            --   if it encounters an error, it does not remove that table from #tablesNeedingCopy so it will try again.
            --   this is because we don't know the order to delete and may encounter foreign key constraints.
            --   It usually deletes all records from all tables after 2 or so loops.

            -- the 2nd step is nearly identical, but instead it inserts the data
            Declare @CopyToDatabase varchar(100)
            declare @CopyFromDatabase varchar(100)

            set @CopyToDatabase = 'WorkflowTest'
            set @CopyFromDatabase = 'Workflow'

            use WorkflowTest -- [Connect to Database that you want to copy to]


            DECLARE @sqlCommand varchar(max)
            declare @columnNames varchar(max)
            DECLARE @tableName as NVARCHAR(100);
            DECLARE @tableNameCursor as CURSOR;

            create table #tablesNeedingCopy
            (
                Table_Name varchar(100)
            )


            insert into #tablesNeedingCopy
            (Table_Name)
            SELECT TABLE_NAME
            FROM INFORMATION_SCHEMA.TABLES 
            WHERE TABLE_TYPE = 'BASE TABLE' 
                and Table_Name not like 'sys%'

            declare @hasTableError as char(1)
            declare @remainingTableCount int
            declare @loopControl int
            set @loopControl = 0

            select @remainingTableCount = count(*)
            from #tablesNeedingCopy

            while (@remainingTableCount > 0 And @loopControl < 10)
            begin


                set @loopControl = @loopControl + 1

                SET @tableNameCursor = CURSOR FOR
                SELECT TABLE_NAME
                FROM #tablesNeedingCopy




                OPEN @tableNameCursor;
                FETCH NEXT FROM @tableNameCursor INTO @tableName;

                WHILE @@FETCH_STATUS = 0
                BEGIN

                set @hasTableError = 'N'


                SET @sqlCommand = 'Delete from ' + @tableName
                print @sqlCommand
                begin try
                    exec (@sqlCommand)
                end try
                begin catch 
                    set @hasTableError = 'Y'
                    print ERROR_MESSAGE()
                end catch



                if (@hasTableError = 'N')
                begin
                    -- otherwise leave the table in
                    delete from #tablesNeedingCopy
                    where Table_Name = @tableName
                end

                FETCH NEXT FROM @tableNameCursor INTO @tableName;
                END

                CLOSE @tableNameCursor;
                DEALLOCATE @tableNameCursor;

                select @remainingTableCount = count(*)
                from #tablesNeedingCopy

            end -- end while


            select @remainingTableCount = count(*)
                from #tablesNeedingCopy


            if (@remainingTableCount > 0)
            begin
            select Table_Name as DeleteTableNames 
            from #tablesNeedingCopy
            end

            delete from  #tablesNeedingCopy

            -------


            insert into #tablesNeedingCopy
            (Table_Name)
            SELECT TABLE_NAME
            FROM INFORMATION_SCHEMA.TABLES 
            WHERE TABLE_TYPE = 'BASE TABLE' 
                and Table_Name not like 'sys%'

            declare @hasIdentityColumn as char(1)
            set @loopControl = 0


            select @remainingTableCount = count(*)
            from #tablesNeedingCopy

            while (@remainingTableCount > 0 And @loopControl < 10)
            begin

                set @loopControl = @loopControl + 1

                SET @tableNameCursor = CURSOR FOR
                SELECT TABLE_NAME
                from #tablesNeedingCopy




                OPEN @tableNameCursor;
                FETCH NEXT FROM @tableNameCursor INTO @tableName;

                WHILE @@FETCH_STATUS = 0
                BEGIN

                set @hasTableError = 'N'
                set @hasIdentityColumn = 'Y'

                SET @sqlCommand = 'SET IDENTITY_INSERT ' + @CopyToDatabase + '.dbo.' + @tableName + ' ON;' -- Database to copy to
                begin try
                    print @sqlCommand
                    exec (@sqlCommand)
                end try
                begin catch 
                --print  ERROR_MESSAGE() 
                set @hasIdentityColumn = 'N'
                end catch


                if (@hasTableError = 'N')
                begin
                    SELECT  top 1 @columnNames =
                        STUFF((SELECT N', ' + Column_Name 
                                FROM INFORMATION_SCHEMA.COLUMNS AS t2 
                                WHERE t2.TABLE_NAME=t.TABLE_NAME 
                                FOR XML PATH,TYPE).value(N'.','nvarchar(max)'),1,2,'')
                    FROM INFORMATION_SCHEMA.COLUMNS t
                    WHERE TABLE_NAME = @tableName
                    order by ORDINAL_POSITION


                    set @sqlCommand = 'Insert into ' + @CopyToDatabase + '.dbo.' + @tableName + ' (' + @columnNames + ') select ' + @columnNames + ' from ' + @CopyFromDatabase + '.dbo.' + @tableName 

                    if (@hasIdentityColumn = 'Y')
                    begin
                    set @sqlCommand = 'SET IDENTITY_INSERT ' + @CopyToDatabase + '.dbo.' + @tableName + ' ON; ' + @sqlCommand + ' SET IDENTITY_INSERT ' + @CopyToDatabase + '.dbo.' + @tableName + ' OFF;'
                    end
                    print @sqlCommand
                    begin try
                        exec (@sqlCommand)
                    end try
                    begin catch
                        set @hasTableError = 'Y'
                        print ERROR_MESSAGE()
                    end catch
                end


                if (@hasTableError = 'N')
                begin
                    -- otherwise leave the table in
                    delete from #tablesNeedingCopy
                    where Table_Name = @tableName
                end

                FETCH NEXT FROM @tableNameCursor INTO @tableName;
                END

                CLOSE @tableNameCursor;
                DEALLOCATE @tableNameCursor;

                select @remainingTableCount = count(*)
                from #tablesNeedingCopy

            end -- end while

            select @remainingTableCount = count(*)
                from #tablesNeedingCopy


            if (@remainingTableCount > 0)
            begin
            select Table_Name as InsertTableNames 
            from #tablesNeedingCopy
            end

            drop table #tablesNeedingCopy