Как создать сценарий T-SQL с SMO - PullRequest
0 голосов
/ 06 июля 2018

У меня есть база данных SQL Server с несколькими таблицами, каждая из которых имеет первичный ключ и несколько ограничений внешнего ключа.

Я хочу сделать резервную копию таблиц базы данных в файл .sql, чтобы я мог восстановить базу данных, как это будет через некоторое время.

Я пробовал пару комбинаций ScriptOptions, но не получил желаемого результата.

Проблема в том, что оператор CREATE для таблиц не отображается в порядке их зависимости. Если таблица A имеет внешний ключ таблицы B, то в моем сценарии оператор CREATE для таблицы A указан первым. Делая это, я не могу восстановить базу данных.

Я пытался использовать ScriptOptions.WithDependencies = true. Но тогда оператор CREATE для таблицы B добавляется дважды, чего я не хочу.

Я использую подход, который заключается в том, чтобы сначала получить только дамп схемы, затем все ограничения и затем дамп данных в одном и том же файле SQL.

Вот мой пример кода C # для этого:

ServerConnection sc = new ServerConnection(args[0], args[1], args[2]);

Server myServer = new Server(sc);
myServer.SetDefaultInitFields(typeof(StoredProcedure), "IsSystemObject");
myServer.SetDefaultInitFields(typeof(UserDefinedFunction), "IsSystemObject");

Database db = default(Database);
db = myServer.Databases[args[3]];

StringBuilder sb = new StringBuilder();
StringBuilder sbConstraints = new StringBuilder();

Scripter dropScrp = default(Scripter);
dropScrp = new Scripter(myServer);
dropScrp.Options.IncludeIfNotExists = true;
dropScrp.Options.ScriptSchema = true;
dropScrp.Options.ScriptDrops = true;

Scripter createScrp = default(Scripter);
createScrp = new Scripter(myServer);
createScrp.Options.IncludeIfNotExists = true;
createScrp.Options.ScriptSchema = true;

Scripter constratintScrp = default(Scripter);
constratintScrp = new Scripter(myServer);
constratintScrp.Options.DriAllKeys = true;

foreach (Table tb in db.Tables)
{
    if (tb.IsSystemObject == false)
    {
        foreach (string s in dropScrp.EnumScript(new Urn[] { tb.Urn }))
        {
            sb.AppendLine(s);
        }

        foreach (string s in createScrp.EnumScript(new Urn[] { tb.Urn }))
        {
            sb.AppendLine(s);
        }

        foreach (string s in constratintScrp.EnumScript(new Urn[] { tb.Urn }))
        {
            sbConstraints.AppendLine(s);
        }
        sb.AppendLine("");
    }
}

sb.AppendLine(sbConstraints.ToString());
File.WriteAllText(args[4], sb.ToString());

1 Ответ

0 голосов
/ 21 сентября 2018

Я решил свою проблему следующим образом:

            StringBuilder sb = new StringBuilder();
            StringBuilder sbConstraints = new StringBuilder();
            StringBuilder sbData = new StringBuilder();

            Scripter dropScrp = default(Scripter);
            dropScrp = new Scripter(myServer);
            dropScrp.Options.IncludeIfNotExists = true;
            dropScrp.Options.ScriptSchema = true;
            dropScrp.Options.ScriptDrops = true;

            Scripter createScrp = default(Scripter);
            createScrp = new Scripter(myServer);
            createScrp.Options.ScriptSchema = true;
            createScrp.Options.NoCommandTerminator = false;
            createScrp.Options.ScriptBatchTerminator = true;
            createScrp.Options.DriPrimaryKey = true;
            createScrp.Options.IncludeIfNotExists = true;

            Scripter constratintScrp = default(Scripter);
            constratintScrp = new Scripter(myServer);
            constratintScrp.Options.Default = false;
            constratintScrp.Options.DriUniqueKeys = true;
            constratintScrp.Options.DriForeignKeys = true;
            constratintScrp.Options.DriPrimaryKey = false;

            Scripter dataScrp = default(Scripter);
            dataScrp = new Scripter(myServer);
            dataScrp.Options.ScriptData = true;
            dataScrp.Options.ScriptSchema = false;

            foreach (Table tb in db.Tables)
            {
                if (tb.IsSystemObject == false)
                {
                    foreach (string s in dropScrp.EnumScript(new Urn[] { tb.Urn }))
                    {
                        sb.AppendLine(s);
                    }

                    foreach (string s in createScrp.EnumScript(new Urn[] { tb.Urn }))
                    {
                        sb.AppendLine(s);
                    }

                    foreach (string s in constratintScrp.EnumScript(new Urn[] { tb.Urn }))
                    {
                        sbConstraints.AppendLine(s);
                    }

                    foreach (string s in dataScrp.EnumScript(new Urn[] { tb.Urn }))
                    {
                        sbData.AppendLine(s);
                    }

                    sb.AppendLine("");
                    sbConstraints.AppendLine("");
                    sbData.AppendLine("");
                }
            }

            sb.AppendLine(sbData.ToString());
            sb.AppendLine(sbConstraints.ToString());

Это создаст скрипт sql в следующем порядке.

  1. для каждого стола
    1. Отбросить оператор с проверкой, если существует.
    2. Создать оператор с проверкой, если не существует. Это также будет включать ограничение первичного ключа.
  2. Вставить операторы данных для каждой таблицы.
  3. Создание оператора ограничений для каждой таблицы (не ограничений первичного ключа).

    Я должен сначала вставить данные в таблицу, прежде чем применять ограничения, потому что у меня нет никакого способа вставить данные в порядке их зависимости. Который был моей оригинальной проблемой также. Итак, я сначала вставил данные, а затем применил ограничения к таблице.

...