保持db结构和procs同步

时间:2009-12-31 19:59:32

标签: sql-server stored-procedures copy smo

我正在尝试设置一个测试数据库,以便自动运行测试。我理所当然地知道我们应该使用模拟对象,但这是一个旧的应用程序,这样做并不像应该的那样容易。数据库中存在太多逻辑。

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

在测试开始时,将运行.sql脚本来清​​空表,然后用测试数据填充它们。我看到的问题并不是保持数据库结构同步,因为它们没有太大变化(尽管那也不错)但是将所有的proc / functions等从dev开始转移到测试开始时测试

是否可以执行SQL命令来执行此操作?从dev db读取proc,并将其复制到测试db?

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

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

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

乍得,我不确定你想要的自动化程度如何。如果您想立即编写所有过程的脚本,可以从SQL企业管理器执行此操作。

在每个测试脚本之前,所有来自Dev for CREATE的过程。在TEST中删除proc并从dev文件运行脚本。这将确保您的触发器同步。

答案 2 :(得分: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

请确保您不要混淆SourceDatabaseDestinationDatabase,否则您将遇到麻烦!

答案 3 :(得分: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;
    }