【发布时间】:2015-01-22 07:19:43
【问题描述】:
我的 SQL 服务器中有一个过程列表,我想用该表的 select(所有列名)替换所有 select * 语句。为此,我需要识别程序脚本的所有选择语句。这是我当前的代码。
foreach (StoredProcedure myproc in SelectedProcedures)
{
StringBuilder builder = new StringBuilder();
ScriptingOptions scriptOptions = new ScriptingOptions();
StringCollection tableScripts = myproc.Script();
foreach (string script in tableScripts)
{
if (script.ToUpper().Contains("CREATE PROCEDURE"))
{
string x = script.ToUpper().Replace("CREATE PROCEDURE", "ALTER PROCEDURE");
builder.Append(x + "\n");
if (script.ToString().ToUpper().Replace(" ", " ").Contains("SELECT * FROM "))
{
string u = script.ToString().ToUpper().Replace(" ", " ");
List<string> values = u.Split(new string[] { "SELECT * FROM " }, StringSplitOptions.RemoveEmptyEntries).ToList();
List<string> tablenames = new List<string>();
values.RemoveAt(0);
foreach (string t in values)
{
if (!t.Trim().StartsWith("#") && !t.Trim().StartsWith("@"))
{
tablenames.Add(t.Split(' ')[0].Replace("[", "").Replace("]", "").ToUpper().Trim());
}
}
tablenames.OrderBy(xx => xx);
List<Table> tables = SourceDB.Tables.Cast<Table>().Where(t => tablenames.Contains(t.ToString().Replace("[", "").Replace("]", "").ToUpper())).Select(t => t).ToList();
foreach (var t in tablenames)
{
try
{
Table mytable = SourceDB.Tables[t.Split('.')[1], t.Split('.')[0]];
if (mytable != null)
{
StringBuilder builder1 = new StringBuilder();
builder1.Append("SELECT ");
foreach (Column column in mytable.Columns)
{
builder1.Append("[" + column.Name.ToUpper() + "], ");
}
builder1.Remove(builder1.ToString().LastIndexOf(", "), 1);
builder1.Append(" from ");
builder1.Append(mytable.ToString());
GeneratedScripts["Procedures"].Add(builder1);
string k = builder.ToString().ToUpper();
string n = k.Replace(" ", " ").Replace("SELECT * FROM " + mytable.ToString().ToUpper(), builder1.ToString());
n = n.Replace(" ", " ").Replace("SELECT * FROM " + t, builder1.ToString());
builder = new StringBuilder(n);
}
}
catch (Exception)
{
continue;
}
}
}
}
}
但是,这省略了 select B.* from table A inner join table B 之类的情况 我可以使用额外的逻辑,如 Regex 来处理这些事情,但我想要一种更合适的方式,以便在字符串列表中检索过程脚本的所有选择查询,然后我可以在所有查询中使用我的自定义逻辑一个接一个。
谢谢
【问题讨论】:
-
为了正确执行此操作,您必须编写一个完整的 SQL 解析器——这不是一件容易的事。你可能想看看做这种事情的商业产品。
-
有一个现有的免费 Api,看看 DacFx 和 TSqlObject,它们将为您提供存储过程中的语句。 qxg 在他的回答中显示的是 ssdt 使用的 api(如果你确实写了它,请 Oss 它,因为它对其他人有用)。
-
它实际上是 ScriptDom 而不是 TSqlObjects,这显示了如何获取语句,但您也可以获取列和表等:blogs.msdn.com/b/arvindsh/archive/2013/04/04/…
标签: c# sql-server smo