在测试过程中,我想在运行测试之前复制同一数据库中的几个表。测试完成后,我想用副本恢复原始表。
最好的方法是什么?
我还想确保所有索引和约束都已恢复。
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
我认为我最近使用的脚本可能对某人有用。
要备份表,您可以使用下一个查询:
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。例如,这可以在存储过程中,因此脚本是可重用的。
首先,将原表复制到新表中:
CREATE TABLE CopiedTable AS SELECT * FROM OriginalTable;
每当您想要恢复时,截断原始数据并将值从副本插入回:
TRUNCATE TABLE OriginalTable
INSERT INTO OriginalTable SELECT * FROM CopiedTable
根据您使用的数据库,有更快的替代方案。
另外,要小心。正如其他人指出的,最安全的方法是备份孔数据库。
您是否考虑过使用 SQL Server 单元测试框架,例如开源 tSQLt 框架?
tSQLt 测试在事务中运行,因此您在测试中所做的任何操作都将回滚。
它有一个“faketable”的概念,它是原始表减去约束的副本(如果这些约束妨碍了您的测试设置)。