Как сделать резервную копию только табличных данных из SQL Server 2008 R2 с помощью C#

Я разработал хорошее приложение с функцией резервного копирования и восстановления. Это работает нормально. каждый раз, когда я добавлял новые функции в базу данных 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?


person Reza Paidar    schedule 01.06.2017    source источник


Ответы (2)


Вы не можете восстановить только данные, но вы можете заскриптовать все свои объекты-модули (вы можете сделать это в несколько щелчков мыши с помощью SSMS), прежде чем восстановить свою резервную копию, а затем удалить все модули и запустить скрипт, который пересоздает все модули .

Обновлять:

если вы не можете использовать SSMS, вы можете написать свои модули, используя

select definition from sys.sql_modules

как инструкции CREATE. Единственное предостережение: ваши объекты никогда не должны переименовываться, потому что определение в sys.sql_modules не обновляется при переименовании модуля.

Другие варианты:

  • сценарий базы данных с данными в виде операторов INSERT (для небольших размеров данных)
  • или импортировать/экспортировать данные с помощью утилита bcp. Это не создает скрипт для какого-либо объекта, поэтому вам следует обрезать свои таблицы перед импортом данных или воссоздать таблицы, если их структура отличается от того, что содержит ваша резервная копия.
person sepupic    schedule 01.06.2017
comment
да, вы правы, но мои клиенты не имеют доступа к SSMS. Приложение устанавливается на SQL Server Express, и все необходимое работает во время выполнения. - person Reza Paidar; 01.06.2017
comment
В этом случае все зависит от того, сколько данных вы хотите импортировать. Для базы данных небольшого размера вы можете написать все таблицы, включая данные, в виде операторов INSERT и запустить этот скрипт. - person sepupic; 01.06.2017
comment
Для больших баз данных вы можете экспортировать свои данные с помощью bcp в плоские файлы, а затем импортировать их, используя тот же bcp. - person sepupic; 01.06.2017
comment
Или вы можете просто создать сценарии создания для всех ваших модулей, используя sys.sql_modules, и запустить этот сценарий после восстановления из резервной копии. - person sepupic; 01.06.2017
comment
Последний вариант для вас: заскриптуйте все свои модули как CREATE с помощью sys.sql_modules, восстановите из резервной копии, запустите скрипты CREATE - person sepupic; 01.06.2017
comment
Можете ли вы обновить свой пост и рассказать мне о BCP или следующем методе? - person Reza Paidar; 01.06.2017

Восстановить в другой среде

Восстановите базу данных в другой базе данных (копии или существующей среде разработки/тестирования).

оператор RESTORE

Затем выберите только необходимые данные и скопируйте их в производственную среду.

Способ выбора данных и вставки их обратно будет полностью зависеть от того, какие данные должны быть переданы, и есть ли какие-либо ограничения для их добавления (индексы, ключи и т. д.).

Восстановить хранимые процедуры

Например, здесь вы можете получить все имена СОХРАНЕННЫХ ПРОЦЕДУР, чтобы удалить их.

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

Просто поместите их в 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]

person Hybris95    schedule 01.06.2017
comment
Вы можете объяснить свою идею с помощью SQL-запроса? - person Reza Paidar; 01.06.2017
comment
Спасибо, позвольте мне изучить ваши методы. - person Reza Paidar; 01.06.2017
comment
Также рассмотрите возможность резервного копирования рабочей базы данных, прежде чем делать все это в качестве меры безопасности. И проголосовать за ответ :) - person Hybris95; 01.06.2017
comment
@Hybrys95 sys.objects не имеет определения таблицы, что вы имели в виду, говоря ›››Также вы можете снова получить определения таблицы из таблицы sys.objects‹‹‹ ? - person sepupic; 01.06.2017
comment
sys.objects содержит имена таблиц, таким образом вы можете перечислить все таблицы, которые могут быть перенесены. Например, если вы хотите перенести все пользовательские таблицы без различий. В противном случае вы можете жестко закодировать имена таблиц в сценарии восстановления, если не хотите использовать определения из базы данных. - person Hybris95; 01.06.2017