2012-06-11 148 views
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 '[email protected]+'_'[email protected]+' from '[email protected] 
SELECT @SQL 

EXEC (@SQL) -- Execute SQl statement 

如果我使用上述方法制作副本,該如何恢復。

SQL2005

回答

1

有許多方法可以做到這一點,但目前爲止,最簡單的方法是簡單地備份數據庫,使用它,然後在完成時從備份中恢復。 (Instructions here

備份表格當然是可行的,但它不是最簡單的方法,一旦你開始使用多個表格,它會變得更加困難。因此,我不提供恢復單個表的特定示例,而是提供通用關於更好地管理測試數據的建議。

這樣做的最安全方式是無法恢復原來,而是甚至沒有接觸到原件。備份它,然後將其恢復到新的測試服務器。 (Instructions here)最佳實踐決定了您不應該在活動數據庫上進行測試或開發工作。這也很容易,也很安全。

+0

備份無法恢復單個表。版本控制存儲表格的定義而不是其內容。 -1 – Andomar

+0

@Andomar,當然你是對的。我刪除了版本控制部分,並進行了編輯以使我的意思更清晰。我同意你的-1,因爲我沒有回答他的具體問題,但是我把它留在這裏,因爲我認爲這比一般回答他的例子還好。感謝您的反饋意見! – David

2

喜歡的東西:

truncate table OriginalTable 
insert into OriginalTable select * from CopiedTable 

取決於你使用的數據庫中,有更快的替代品。

1

您是否考慮過使用SQL Server單元測試框架,如開源tSQLt框架?

查看交易你這樣做無論在您的測試將得到回滾http://tsqlt.org/

一個tSQLt測試運行。

它有一個「faketable」的概念,它是原始表的副本減去約束,如果這些妨礙了你的測試設置。

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_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。例如,這可以在一個存儲過程中,所以腳本是可重用的。