如何在C#中从storedprocedure脚本中查找所有选择查询

时间:2015-01-22 07:19:43

标签: c# sql-server smo

我的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)来处理这些事情,但我想要一个更合适的方法,以便在字符串列表中检索过程脚本的所有选择查询,然后我可以在所有查询上使用我的自定义逻辑一个接一个。

由于

2 个答案:

答案 0 :(得分:1)

如果您的数据库是由SSDT开发的,这很容易,在Visual Studio 2013之后默认包含SSDT。在SSDT中,只需右键单击项目节点,然后选择Refactor - &gt;展开通配符。 SSDT在内部构建了一个数据库模式模型,因此很容易找到准确的列。

使用此工具(我相信其他工具),您仍需要关注EXISTS (SELECT * FROMSELECT COUNT(*)之类的查询。更换它们没有多大意义。 enter image description here

答案 1 :(得分:-1)

我会做一些假设:

查找正则表达式匹配,其中*和SELECT之间出现*。 如果SELECT前面紧跟一个'EXISTS('可能包含或不包含空格或制表符),则只有可能的排除。

其他替代方案是只关注执行计划缓存并查找最常用的查询。

另一个伟大的(或更好的)替代方案是开始进行代码分析,其中可能包含此规则。