【问题标题】:How to backup only table data from SQL Server 2008 R2 using C#如何使用 C# 从 SQL Server 2008 R2 仅备份表数据
【发布时间】:2017-06-01 07:39:59
【问题描述】:

我开发了一个具有备份和恢复功能的优秀应用程序。它工作正常。每次我为其 SQL Server 2008 R2 数据库添加新功能时,例如添加新的存储过程或用户定义的表类型来升级我的软件。

我的备份功能是这样的:

protected int BackUpDataBase(string dbName, string address)
{
    try
    {
        using (_con)
        {
            string command = "Backup database " + dbName + " to disk='" + address + "'";
            SqlCommand cmd = new SqlCommand(command, _con);
            cmd.CommandType = CommandType.Text;
            connect();
            cmd.ExecuteNonQuery();
            return 1;
        }
    }
    catch (SqlException ex)
    {
        return ex.Number * (-1);
    }
}

我的恢复功能在这里:

protected int RecoverDataBase(string dbName, string address)
{
    try
    {
        SqlConnection temp = new SqlConnection(_addressMaster);
        string Restore = "USE master" + Environment.NewLine;
        if (CheckDatabaseExists(dbName))
        {
            Restore += @"ALTER DATABASE [" + dbName + "]" + Environment.NewLine;
            Restore += @"SET OFFLINE WITH ROLLBACK IMMEDIATE" + Environment.NewLine;
            Restore += @"ALTER DATABASE [" + dbName + "] SET ONLINE" + Environment.NewLine;
        }
        Restore += @"RESTORE DATABASE [" + dbName + "] FROM DISK = N'" + address + @"' WITH FILE = 1,  NOUNLOAD, REPLACE, STATS = 10" + Environment.NewLine;
        Restore += @"ALTER DATABASE [" + dbName + "] SET Single_User WITH Rollback Immediate" + Environment.NewLine;
        Restore += @"ALTER DATABASE [" + dbName + "] SET Multi_User" + Environment.NewLine;
        using (temp)
        {
            using (SqlCommand cmd = new SqlCommand(Restore, temp))
            {
                cmd.CommandText = Restore;
                cmd.CommandType = CommandType.Text;
                temp.Open();
                cmd.ExecuteNonQuery();
                temp.Close();
                return 1;
            }
        }
    }
    catch (SqlException ex)
    {
        return ex.Number * (-1);
    }
}

一切都很好,但是!问题出在这里:我用新的存储过程等开发了升级后的 Windows 应用程序,然后将其安装到新计算机上,并希望将旧备份恢复到升级后的应用程序,所有新的存储过程和功能都将恢复到旧的,因为我恢复了整个旧备份不仅是它的数据。 那么如何使用 C# 和 SQL 查询从备份文件中仅恢复表数据呢?

【问题讨论】:

    标签: c# sql-server sql-server-2008-r2 database-backups database-restore


    【解决方案1】:

    您不能只恢复数据,但是您可以在恢复备份之前编写所有对象模块的脚本(您可以使用 SSMS 通过鼠标单击来完成),然后删除所有模块并启动重新创建的脚本所有模块。

    更新:

    如果你不能使用 SSMS,你可以使用脚本编写你的模块

    select definition from sys.sql_modules
    

    作为 CREATE 语句。 这里唯一需要注意的是,您的对象永远不能重命名,因为重命名模块时不会更新 sys.sql_modules 中的定义。

    其他选项有:

    • 使用数据作为 INSERT 语句编写数据库脚本(对于小型 数据大小)
    • 或使用bcp utility 导入/导出数据。这不是脚本 任何对象,因此您应该在导入数据之前截断表 或者如果它们的结构与您的不同,则重新创建表 备份包含

    【讨论】:

    • 是的,您是对的,但我的客户无法访问 SSMS。应用程序安装在 SQL Server Express 上,所需的一切都运行运行时。
    • 在这种情况下,一切都取决于您要导入多少数据。对于小型数据库,您可以将包括数据在内的所有表编写为 INSERT 语句并启动此脚本
    • 对于大型数据库,您可以在平面文件中使用 bcp 导出数据,然后使用相同的 bcp 导入它们
    • 或者您可以使用 sys.sql_modules 为所有模块创建创建脚本,并在从备份恢复后启动此脚本
    • 最后一个选项适合您:使用 sys.sql_modules 将所有模块编写为 CREATE,从备份恢复,启动 CREATE 脚本
    【解决方案2】:

    恢复到另一个环境

    在另一个数据库(副本或现有的开发/测试环境)上恢复您的数据库。

    RESTORE statement

    然后只选择需要的数据并将它们复制到生产环境中。

    选择数据并将它们插入回去的方式将完全取决于必须传输的数据,以及添加它们是否有任何限制(索引、键等...)

    恢复存储过程

    例如,您可以在此处获取所有 STORED PROCEDURE 名称以删除它们。

    SELECT 'DROP PROCEDURE ' + objects.name FROM sys.sql_modules
    INNER JOIN sys.objects
    ON objects.object_id = sql_modules.object_id
    WHERE objects.type_desc = 'SQL_STORED_PROCEDURE'
    

    然后您可以使用以下查询恢复创建脚本

    SELECT sql_modules.definition FROM sys.sql_modules
    INNER JOIN sys.objects
    ON objects.object_id = sql_modules.object_id
    WHERE objects.type_desc = 'SQL_STORED_PROCEDURE'
    

    DROP Procedure

    只需将它们放在EXEC 中,并确保它在生产数据库上执行,并从复制数据库中选择数据。

    恢复数据(无索引和键)

    DROP TABLE [prodDB].[mySchema].[myTable]
    SELECT * INTO [prodDB].[mySchema].[myTable] FROM [copyDB].[mySchema].[myTable]
    

    您还可以再次从sys.objects 表中获取表定义。

    SELECT schemas.name + '.' + objects.name FROM sys.objects
    INNER JOIN sys.schemas
    ON objects.schema_id = schemas.schema_id
    WHERE type_desc = 'USER_TABLE'
    

    恢复数据(使用索引和键)

    TRUNCATE TABLE [prodDB].[mySchema].[myTable]
    INSERT INTO [prodDB].[mySchema].[myTable] SELECT * FROM [copyDB].[mySchema].[myTable]
    

    如果您有任何外键引用恢复的表,也可以考虑阅读这篇文章:https://stackoverflow.com/a/253858/3635715

    如果您需要获取键定义,您可以从[sys].[key_constraints] 获取它们

    【讨论】:

    • 你能用 SQL 查询解释一下你的想法吗?
    • 谢谢让我研究一下你的方法。
    • 还可以考虑在执行所有这些操作之前备份生产数据库作为安全措施。并支持答案:)
    • @Hybrys95 sys.objects 没有任何表定义,你的意思是什么>>>另外你可以再次从 sys.objects 表中获取表定义
    • sys.objects 包含表名,这样您可以列出所有可能被转移的表。例如,如果您想无区别地传输所有用户表。否则,如果您不想使用数据库中的定义,可以在恢复脚本中对表名进行硬编码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多