首页 > 解决方案 > 如何使用 SMO 生成 T-SQL 脚本

问题描述

我有一个 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());

标签: sql-serverdatabasebackupsmo

解决方案


我这样解决了我的问题:

            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. 使用 if 存在检查删除语句。
    2. 如果不存在检查创建语句。这也将包括主键约束。
  2. 为每个表插入数据语句。
  3. 为每个表创建约束语句(不是主键约束)。

    在应用约束之前,我必须先将数据插入表中,因为我没有任何方法可以按依赖顺序插入数据。这也是我原来的问题。所以,我首先插入数据,然后在表上应用约束。


推荐阅读