sql-server - 如何使用 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());
解决方案
我这样解决了我的问题:
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 脚本。
- 对于每张桌子
- 使用 if 存在检查删除语句。
- 如果不存在检查创建语句。这也将包括主键约束。
- 为每个表插入数据语句。
为每个表创建约束语句(不是主键约束)。
在应用约束之前,我必须先将数据插入表中,因为我没有任何方法可以按依赖顺序插入数据。这也是我原来的问题。所以,我首先插入数据,然后在表上应用约束。
推荐阅读
- flutter - 将json解析成flutter List
到地图 - css - 未设置 headerfilter 时制表符垂直对齐标题
- python - 使用多个 buildpack 在 Heroku 上部署 Haskell + Python
- java - 在没有 JRE 的情况下安装 tabula-py
- python - 无法通过 Telethone 在 Megagroup 中发送消息
- amazon-web-services - 为什么 AWS Route 53 不发布我的 DNS 记录?
- c# - 在 .Net Core 中为 WEB API 控制器定义不同的(不同于全局的)CORS 策略
- sql - 在 SQL 计算中使用两个列别名
- ceph - 如何修复重启后挂起的 ceph 命令?
- html - 试图了解图像裁剪的对象拟合