我的SQL服务器中有一个程序列表,我想用该表的select(所有列名)替换所有select *语句。为此,我需要识别procudure脚本的所有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;
}
}
}
}
}
然而,这省略了表A内连接表B中的select B. *之类的情况 我可以使用其他逻辑(如Regex)来处理这些事情,但我想要一个更合适的方法,以便在字符串列表中检索过程脚本的所有选择查询,然后我可以在所有查询上使用我的自定义逻辑一个接一个。
由于
答案 0 :(得分:1)
如果您的数据库是由SSDT开发的,这很容易,在Visual Studio 2013之后默认包含SSDT。在SSDT中,只需右键单击项目节点,然后选择Refactor - &gt;展开通配符。 SSDT在内部构建了一个数据库模式模型,因此很容易找到准确的列。
使用此工具(我相信其他工具),您仍需要关注EXISTS (SELECT * FROM
或SELECT COUNT(*)
之类的查询。更换它们没有多大意义。
答案 1 :(得分:-1)
我会做一些假设:
查找正则表达式匹配,其中*和SELECT之间出现*。 如果SELECT前面紧跟一个'EXISTS('可能包含或不包含空格或制表符),则只有可能的排除。
其他替代方案是只关注执行计划缓存并查找最常用的查询。
另一个伟大的(或更好的)替代方案是开始进行代码分析,其中可能包含此规则。