Sql server 将SQL Server数据库复制到测试数据库的最简单方法?

Sql server 将SQL Server数据库复制到测试数据库的最简单方法?,sql-server,database,sql-server-2008,Sql Server,Database,Sql Server 2008,获取SQL Server数据库并制作其测试副本的最简单方法是什么 我已经浏览了一些现有的主题,但不确定是否有更简单的方法。我有一个数据库发布者。我希望能够将这两个数据库保持在同一台服务器上 更新:我使用MicrosoftSQLServer发布向导来编写文件脚本、创建新数据库、添加“UseDB”并执行脚本。这似乎很管用。不建议附加/分离,因为如果它是全文搜索数据库或日志丢失,它会将链接保留回原始位置。删除数据库(意味着使其脱机),复制mdf文件,然后重新附加原始和副本。我只会创建数据库,然后使用“

获取SQL Server数据库并制作其测试副本的最简单方法是什么

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


更新:我使用MicrosoftSQLServer发布向导来编写文件脚本、创建新数据库、添加“UseDB”并执行脚本。这似乎很管用。不建议附加/分离,因为如果它是全文搜索数据库或日志丢失,它会将链接保留回原始位置。

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

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


也许不是最简单的方法,但是很低调。您还可以将数据写入一个文件,并将其回放到一个新的数据库中——这需要一段时间,但对于版本控制之类的事情来说,它很方便,而且它是人类可读的(嗯,“开发人员”)。

我总是先备份它,然后恢复到不同的名称/文件集;
或者您可以创建一个空数据库&使用恢复“向导”启用覆盖和更改恢复文件路径。

我经常使用完全相同架构的测试和实时数据库。它们通常具有存储过程,根据开发更改的状态进行更改。所以我不能总是备份和恢复。我编写了一个查询,它遍历数据库中的所有表,删除数据。然后再次循环并从实时数据库插入。 在下面的示例中,我的测试数据库称为WorkflowTest,而我的live称为Workflow,但您只需替换变量中的数据库名称即可。只需确保连接到测试数据库即可

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

我发现我的所有45个左右的表都在大约2-3个循环中完全重新填充

在Insert循环期间,它首先通过尝试打开identity_Insert来检查表是否具有标识列。如果这没有失败,那么它将构建一个insert语句,前面的标识为On,后面的标识为off。它必须在同一个EXEC语句中执行,因为EXEC中的命令在执行后会超出范围

事后看来,我想我本可以把所有的测试存储过程都写成alter语句,从活动数据库的备份中恢复测试数据库,然后执行alter语句。但我发现用户安全设置无法正确恢复,所以有时这也会带来麻烦

--获取测试数据库中所有表的列表
--第一个循环遍历它们并删除所有记录。
--如果遇到错误,它不会从#tablesNeedingCopy中删除该表,因此将重试。
--这是因为我们不知道删除的顺序,可能会遇到外键约束。
--它通常会在大约2个循环后从所有表中删除所有记录。
--第二步几乎相同,但它插入了数据
声明@CopyToDatabase varchar(100)
声明@CopyFromDatabase varchar(100)
set@CopyToDatabase='WorkflowTest'
设置@CopyFromDatabase='Workflow'
使用WorkflowTest--[连接到要复制到的数据库]
声明@sqlCommand varchar(最大值)
声明@columnNames varchar(最大值)
声明@tableName为NVARCHAR(100);
将@tableNameCursor声明为游标;
创建表#表需要复制
(
表_Name varchar(100)
)
插入到需要复制的表中
(表格名称)
选择表格名称
来自信息\u SCHEMA.TABLES
其中TABLE_TYPE='基表'
表名称与“sys%”不同
将@hasTableError声明为char(1)
声明@remaingtablecount int
声明@loopcontrolint
设置@loopControl=0
选择@remaingtablecount=count(*)
从#表需要复制
而(@remainingTableCount>0且@loopControl<10)
开始
设置@loopControl=@loopControl+1
设置@tableNameCursor=用于
选择表格名称
从#表需要复制
打开@tableNameCursor;
将下一步从@tableNameCursor提取到@tableName;
而@@FETCH\u STATUS=0
开始
set@hasTableError='N'
SET@sqlCommand='Delete from'+@tableName
打印@sqlCommand
开始尝试
exec(@sqlCommand)
结束尝试
开始捕捉
set@hasTableError='Y'
打印错误消息()
端接
如果(@hasTableError='N')
开始
--否则就把桌子留在里面
从#表中删除需要复制
其中Table_Name=@tableName
结束
将下一步从@tableNameCursor提取到@tableName;
结束
关闭@tableNameCursor;
取消分配@tableNameCursor;
选择@remaingtablecount=count(*)
从#表需要复制
结束
选择@remaingtablecount=count(*)
从#表需要复制
如果(@rema
            -- 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