1

在我的测试过程中,我想在运行测试之前复制同一个数据库中的几个表。测试完成后,我想用副本恢复原始表。

做这个的最好方式是什么?
我还想确保恢复所有索引和约束。

DECLARE @Tablename NVARCHAR(500)
DECLARE @BuildStr NVARCHAR(500)
DECLARE @SQL NVARCHAR(500)
SELECT @Tablename = 'my_Users'
SELECT @BuildStr = CONVERT(NVARCHAR(16),GETDATE(),120)
SELECT @BuildStr = REPLACE(REPLACE(REPLACE(REPLACE(@BuildStr,' 
',''),':',''),'-',''),' ','')
SET @SQL = 'select * into '+@Tablename+'_'+@BuildStr+' from '+@Tablename
SELECT @SQL

EXEC (@SQL) -- Execute SQl statement

如果我使用上述方法进行复制,如何恢复。

SQL2005

4

4 回答 4

2

就像是:

truncate table OriginalTable
insert into OriginalTable select * from CopiedTable

根据您使用的数据库,有更快的替代方案。

于 2012-06-11T16:00:35.613 回答
1

有很多方法可以做到这一点,但到目前为止,最简单的方法是简单地备份数据库,使用它,然后在完成后从备份中恢复。(这里有说明

备份表当然是可行的,但这不是最简单的方法,而且一旦您开始使用多个表,它就会变得更加困难。因此,我没有解决您恢复单个表的具体示例,而是提供有关更好地管理测试数据的一般建议。

安全的方法是不恢​​复原件,甚至不要触摸原件。对其进行备份,然后将其还原到新的测试服务器。(此处的说明)最佳实践表明,无论如何您都不应该在实时数据库上进行测试或开发工作。这也很容易,也很安全。

于 2012-06-11T16:06:37.350 回答
1

您是否考虑过使用诸如开源 tSQLt 框架之类的 SQL Server 单元测试框架?

http://tsqlt.org/

tSQLt 测试在事务中运行,因此您在测试中所做的任何事情都会回滚。

它有一个“faketable”的概念,它是原始表的副本减去约束,如果这些妨碍您的测试设置。

于 2012-06-11T20:43:45.497 回答
1

我认为我最近使用的脚本可能对某人有用。

要备份表,您可以使用下一个查询:

DECLARE @tableName nvarchar(max), @tableName_bck nvarchar(max)
SET @tableName = 'SomeTable';
SET @tableName_bck = 'SomeTable_bck';


-- Backup
DECLARE @insertCommand nvarchar(max)
--SELECT INTO SomeTable_bck FROM SomeTable
SET @insertCommand = 'SELECT * INTO ' + @tableName_bck + ' FROM ' + @tableName
PRINT @insertCommand
EXEC sp_executesql @insertCommand

对于恢复,由于表通常可以有 IDENTITY 字段,因此您需要 SET IDENTITY_INSERT ON 并且在插入记录时还需要提供列列表。这就是脚本有点复杂的原因:

DECLARE @tableName nvarchar(max), @tableName_bck nvarchar(max)
SET @tableName = 'SomeTable';
SET @tableName_bck = 'SomeTable_bck';

-- Restore
DECLARE @columnList nvarchar(max)
DECLARE @insertCommand nvarchar(max)

SELECT
    @columnList = SUBSTRING(
        (
            SELECT ', ' + column_name AS [text()]
            From INFORMATION_SCHEMA.COLUMNS
            WHERE table_name = @tableName
            ORDER BY table_name
            For XML PATH ('')
        ), 2, 1000);

--INSERT INTO SomeTable(Column1, Column2) SELECT Column1, Column2 FROM SomeTable_bck        
SELECT @insertCommand = 'INSERT INTO ' + @tableName + '(' + @columnList + ') SELECT ' + @columnList + ' FROM ' + @tableName_bck

IF EXISTS (
    SELECT column_name, table_name
    FROM INFORMATION_SCHEMA.COLUMNS
       WHERE table_schema = 'dbo' AND table_name = @tableName
       AND COLUMNPROPERTY(object_id(table_name), column_name, 'IsIdentity') = 1
    )
BEGIN
    SET @insertCommand = 
          'SET IDENTITY_INSERT ' + @tableName + ' ON;' 
        + 'TRUNCATE TABLE ' + @tableName + ';'
        + @insertCommand + ';'
        + 'SET IDENTITY_INSERT ' + @tableName + ' OFF;' 
    /*  
    SET IDENTITY_INSERT SomeTable ON
    TRUNCATE TABLE SomeTable
    INSERT INTO SomeTable(Column1, Column2) SELECT Column1, Column2 FROM SomeTable_bck    
    SET IDENTITY_INSERT SomeTable OFF
    */
END
ELSE
BEGIN
    SET @insertCommand = 
        'TRUNCATE TABLE ' + @tableName + ';'
        + @insertCommand
    /*
    TRUNCATE TABLE SomeTable
    INSERT INTO SomeTable(Column1, Column2) SELECT Column1, Column2 FROM SomeTable_bck     
    */
END 

PRINT @insertCommand
EXEC sp_executesql @insertCommand

很容易看出,您可以根据自己的喜好指定@tableName 和@tableName_bck。例如,这可以在存储过程中,因此脚本是可重用的。

于 2016-05-16T15:02:17.437 回答