1

我正在尝试为要运行的自动化测试设置一个测试数据库。我知道理想情况下我们应该使用模拟对象,但这是一个旧应用程序,这样做并不像应有的那么容易。数据库中的逻辑太多了。

无论如何,足够的背景故事。我得到了一个干净的数据库设置,测试可以加载已知数据,因此结果也是已知的。

在测试开始时,将运行一个 .sql 脚本来清空表,然后用测试数据填充它们。我看到的问题与其说是保持数据库结构同步,不如说它们没有太大变化(尽管那也很好),而是在开始时将所有 procs/functions 等从 dev 移动到 test测试。

是否有可以执行的 SQL 命令来执行此操作?从开发数据库中读取一个过程,并将其复制到测试数据库?

编辑:我实际上发现使用 SQL 管理对象效果很好。

唯一的问题是,如果有人重命名了一个项目,sql server 不会更新内部引用,而是以旧名称创建的。有没有办法来解决这个问题?

4

4 回答 4

3

您说保持“数据库结构”同步不是问题,但是您接着说您需要将 procs/functions 从开发移动到测试。这些是数据库结构的一部分!IAC,我建议使用像 Red-Gate 的 SQL 比较这样的工具。它将移动 dev 上存在的任何在测试中不存在的数据库结构。非常好的工具。我已经用了很多年了。

于 2009-12-31T20:03:08.073 回答
3

乍得,我不确定您希望如何实现自动化。如果您想一次编写所有过程的脚本,您可以从 SQL 企业管理器中完成。

在每个测试脚本之前,来自 Dev 的所有 procs 用于 CREATE。将您的 procs 放入 TEST 并从 dev 文件运行脚本。这将确保您的 proc 同步。

于 2009-12-31T20:16:02.163 回答
1

这是一个快速而简单的 SQL 脚本,可用于将存储过程从一个数据库复制到另一个数据库:

USE DestinationDatabase

GO

DECLARE
    @SchemaName sysname,
    @ProcName nvarchar(4000),
    @ProcDefinition nvarchar(max),
    @DropSql nvarchar(4000)

SET @SchemaName = 'dbo'

DECLARE crProcedures CURSOR FAST_FORWARD FOR
    SELECT r.ROUTINE_NAME, r.ROUTINE_DEFINITION
    FROM SourceDatabase.INFORMATION_SCHEMA.Routines r
    WHERE ROUTINE_SCHEMA = @SchemaName
    AND ROUTINE_NAME IN ('Procedure1', 'Procedure2', 'Procedure3')
OPEN crProcedures
FETCH NEXT FROM crProcedures INTO @ProcName, @ProcDefinition
WHILE (@@FETCH_STATUS = 0)
BEGIN
    SET @DropSql = 'IF  EXISTS ' +
        '(SELECT * FROM sys.objects ' +
        'WHERE object_id = OBJECT_ID(N''' + @ProcName + ''') ' +
        'AND type in (N''P'', N''PC'')) ' +
        'DROP PROCEDURE ' + @ProcName
    EXEC sp_executesql @DropSql
    EXEC sp_executesql @ProcDefinition

    FETCH NEXT FROM crProcedures INTO @ProcName, @ProcDefinition
END
CLOSE crProcedures
DEALLOCATE crProcedures

只要确保你不要混淆SourceDatabaseand DestinationDatabase,否则你会遇到麻烦!

于 2009-12-31T20:22:32.647 回答
0

使用 SMO,以下效果很好!并在约 40 秒内复制。

    private static void CopyDBSchema(string sourceDBServer, string sourceDBName, string targetDBServer, string targetDBName)
    {
        Server server = new Server(sourceDBServer);
        server.SetDefaultInitFields(true);

        Database db = server.Databases[sourceDBName];
        Transfer t = new Transfer()
        {
            Database = db,

            CopyData = false,
            CopyAllObjects = false,
            CopyAllUsers = false,
            CopyAllLogins = false,

            CopySchema = true,
            CopyAllTables = true,
            CopyAllViews = true,
            CopyAllStoredProcedures = true,
            CopyAllDatabaseTriggers = true,
            CopyAllUserDefinedAggregates = true,
            CopyAllUserDefinedDataTypes = true,
            CopyAllUserDefinedFunctions = true,
            CopyAllUserDefinedTypes = true,

            DropDestinationObjectsFirst = true,
            UseDestinationTransaction = true,
            DestinationServer = targetDBServer,
            DestinationDatabase = targetDBName
        };

        t.Options.WithDependencies = true;
        t.Options.IncludeIfNotExists = true;
        t.Options.DriPrimaryKey = true;
        t.Options.DriForeignKeys = true;
        t.Options.DriIndexes = true;
        t.Options.DriNonClustered = true;
        t.Options.DriUniqueKeys = true;
        t.Options.DriAllKeys = true;
        t.Options.Triggers = true;

        t.TransferData();
        server = null;
    }
于 2009-12-31T22:37:06.593 回答