将exec sp_executesql转换为普通查询的简便方法?

28 sql-server format macros ssms sp-executesql

在使用Profiler和SSMS处理调试查询时,我很常见的是从Profiler复制查询并在SSMS中测试它们.因为我使用参数化的sql,我的查询都是作为exec sp_executesql查询发送的.

exec sp_executesql 
N'/*some query here*/', 
N'@someParameter tinyint',
@ someParameter =2
Run Code Online (Sandbox Code Playgroud)

我将把它转换成普通的查询以便于编辑(智能感知,错误检查,行号等):

DECLARE @someParameter tinyint
SET @someParameter = 2

/*some query here*/
Run Code Online (Sandbox Code Playgroud)

当然,查询越大越复杂,就越难做到这一点.当你多次来回走动时,它可能是一个痛苦的屁股,并吸收大量的时间.

是否有一种简单的(例如,宏命令)方式将muh executionql转换为更方便的东西?

Mat*_*rts 39

我花了一点时间制作一个简单的脚本,为我做了这个.这是一个WIP,但我在它前面贴了一个(非常难看的)网页,如果你想尝试它现在在这里托管:

http://execsqlformat.herokuapp.com/

样本输入:

exec sp_executesql 
          N'SELECT * FROM AdventureWorks.HumanResources.Employee 
          WHERE ManagerID = @level',
          N'@level tinyint',
          @level = 109;
Run Code Online (Sandbox Code Playgroud)

并输出:

BEGIN
DECLARE @level tinyint;

SET @level = 109;

SELECT * FROM AdventureWorks.HumanResources.Employee  
          WHERE ManagerID = @level
END
Run Code Online (Sandbox Code Playgroud)

我从输入中获取实际SQL语句的格式是使用http://sqlformat.appspot.com上的API完成的.

  • 把它变成一个git仓库让你享受;)https://github.com/mattwoberts/execsqlformat (2认同)
  • https://github.com/wangzq/convert-sp_executesql/blob/master/convert-sp_executesql.cs (2认同)

Tob*_*oby 5

我正在寻找类似的东西,所以我在LinqPad中使用它,只需将sp_executesql语句复制到剪贴板并在LinqPad中运行代码.它输出SQL语句.

void Main()
{
    ConvertSql(System.Windows.Forms.Clipboard.GetText()).Dump();
}

private static string ConvertSql(string origSql)
{
  string tmp = origSql.Replace("''", "~~");       
  string baseSql;
  string paramTypes;
  string paramData = "";
  int i0 = tmp.IndexOf("'") + 1;
  int i1 = tmp.IndexOf("'", i0);
  if (i1 > 0)
  {
      baseSql = tmp.Substring(i0, i1 - i0); 
      i0 = tmp.IndexOf("'", i1 + 1);
      i1 = tmp.IndexOf("'", i0 + 1);
      if (i0 > 0 && i1 > 0)
      {
          paramTypes = tmp.Substring(i0 + 1, i1 - i0 - 1);
          paramData = tmp.Substring(i1 + 1);
      }
  }
  else
  {
      throw new Exception("Cannot identify SQL statement in first parameter");
  }

  baseSql = baseSql.Replace("~~", "'");  
  if (!String.IsNullOrEmpty(paramData))  
  {
      string[] paramList = paramData.Split(",".ToCharArray());
      foreach (string paramValue in paramList)
      {
          int iEq = paramValue.IndexOf("=");
          if (iEq < 0)
              continue;
          string pName = paramValue.Substring(0, iEq).Trim();
          string pVal = paramValue.Substring(iEq + 1).Trim();
          baseSql = baseSql.ReplaceWholeWord(pName, pVal);
      }
  }

  return baseSql;
}

public static class StringExtensionsMethods
{
   /// <summary>
   /// Replaces the whole word.
   /// </summary>
   /// <param name="s">The s.</param>
   /// <param name="word">The word.</param>
   /// <param name="replacement">The replacement.</param>
   /// <returns>String.</returns>
   public static String ReplaceWholeWord(this String s, String word, String replacement)
   {
       var firstLetter = word[0];
       var sb = new StringBuilder();
       var previousWasLetterOrDigit = false;
       var i = 0;
       while (i < s.Length - word.Length + 1)
       {
           var wordFound = false;
           var c = s[i];
           if (c == firstLetter)
               if (!previousWasLetterOrDigit)
                   if (s.Substring(i, word.Length).Equals(word))
                   {
                       wordFound = true;
                       var wholeWordFound = true;
                       if (s.Length > i + word.Length)
                       {
                           if (Char.IsLetterOrDigit(s[i + word.Length]))
                               wholeWordFound = false;
                       }

                       sb.Append(wholeWordFound ? replacement : word);

                       i += word.Length;
                   }

           if (wordFound) continue;

           previousWasLetterOrDigit = Char.IsLetterOrDigit(c);
           sb.Append(c);
           i++;
       }

       if (s.Length - i > 0)
           sb.Append(s.Substring(i));

       return sb.ToString();
   }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*hev 5

我花了一些时间,对Matt Roberts / Wangzq解决方案进行了小的修改,没有DECLAREs部分,您可以在.NET Fiddle上进行尝试或下载LINQPad 5文件

输入:

exec sp_executesql N'UPDATE MyTable SET [Field1] = @0, [Field2] = @1',N'@0 nvarchar(max) ,@1 int',@0=N'String',@1=0
Run Code Online (Sandbox Code Playgroud)

输出:

UPDATE MyTable SET [Field1] = N'String', [Field2] = 0
Run Code Online (Sandbox Code Playgroud)

码:

using System;
using System.Linq;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        var sql = @"exec sp_executesql N'UPDATE MyTable SET [Field1] = @0, [Field2] = @1',N'@0 nvarchar(max) ,@1 int',@0=N'String',@1=0";
        Console.WriteLine(ConvertSql(sql));
    }

    public static string ConvertSql(string origSql)
    {
        var re = new Regex(@"exec*\s*sp_executesql\s+N'([\s\S]*)',\s*N'(@[\s\S]*?)',\s*([\s\S]*)", RegexOptions.IgnoreCase); // 1: the sql, 2: the declare, 3: the setting
        var match = re.Match(origSql);
        if (match.Success)
        {
            var sql = match.Groups[1].Value.Replace("''", "'");
            //var declare = match.Groups[2].Value;
            var setting = match.Groups[3].Value + ',';

            // to deal with comma or single quote in variable values, we can use the variable name to split
            var re2 = new Regex(@"@[^',]*?\s*=");
            var variables = re2.Matches(setting).Cast<Match>().Select(m => m.Value).ToArray();
            var values = re2.Split(setting).Where(s=>!string.IsNullOrWhiteSpace(s)).Select(m => m.Trim(',').Trim().Trim(';')).ToArray();

            for (int i = variables.Length-1; i>=0; i--)
            {
                sql = Regex.Replace(sql, "(" + variables[i].Replace("=", "")+")", values[i], RegexOptions.Singleline);
            }
            return sql;     
        }

        return @"Unknown sql query format.";
    }
}
Run Code Online (Sandbox Code Playgroud)


Zyp*_*rax 1

我不知道现有的插件可以做到这一点。但你可以创建一个:)

一些正则表达式和一些字符串连接,然后将其出售给 Vinko 和其他寻求此功能的人。

如果您想深入研究这一点,这里有一些有关创建 SSMS 插件的信息: http://sqlblogcasts.com/blogs/jonsayce/archive/2008/01/15/building-a-sql-server-management- studio-addin.aspx