Sql server 将exec sp_executesql转换为普通查询的简单方法?
在使用探查器和SSMS处理调试查询时,我通常会从探查器复制查询并在SSMS中测试它们。因为我使用参数化sql,所以我的查询都作为exec sp_executesql查询发送Sql server 将exec sp_executesql转换为普通查询的简单方法?,sql-server,macros,format,ssms,sp-executesql,Sql Server,Macros,Format,Ssms,Sp Executesql,在使用探查器和SSMS处理调试查询时,我通常会从探查器复制查询并在SSMS中测试它们。因为我使用参数化sql,所以我的查询都作为exec sp_executesql查询发送 exec sp_executesql N'/*some query here*/', N'@someParameter tinyint', @ someParameter =2 我将把它转换成一个普通的查询,以便于编辑(智能感知、错误检查、行号等): 当然,查询越大、越复杂,就越难做到这一点。当你来回走很多次的时候,这
exec sp_executesql
N'/*some query here*/',
N'@someParameter tinyint',
@ someParameter =2
我将把它转换成一个普通的查询,以便于编辑(智能感知、错误检查、行号等):
当然,查询越大、越复杂,就越难做到这一点。当你来回走很多次的时候,这会让你感到很痛苦,会占用很多时间
是否有一种简单的方法(例如宏命令)将muh executesql转换为更方便的格式?我不知道现有的外接程序可以这样做。但您可以创建一个:) 一些正则表达式和一些字符串连接,然后卖给Vinko和其他寻找此功能的灵魂 如果您想深入了解这一点,以下是有关创建SSMS插件的一些信息:
我花了一点时间制作了一个简单的脚本,为我做到了这一点。这是一个WIP,但我在它前面贴了一个(非常难看的)网页,如果你想试试的话,它现在托管在这里: 样本输入:
exec sp_executesql
N'SELECT * FROM AdventureWorks.HumanResources.Employee
WHERE ManagerID = @level',
N'@level tinyint',
@level = 109;
以及输出:
BEGIN
DECLARE @level tinyint;
SET @level = 109;
SELECT * FROM AdventureWorks.HumanResources.Employee
WHERE ManagerID = @level
END
从输入中提取实际SQL语句后,将使用API在另一个直接替换查询中的参数值的解决方案中对其进行格式化 (不完全是您要求的,但可能对其他人有用): 我来自:
exec sp_executesql N'UPDATE Task SET Status = @p0, Updated = @p1 WHERE Id = @p2 AND Status = @p3 AND Updated = @p4',N'@p0 int,@p1 datetime,@p2 int,@p3 int,@p4 datetime',@p0=1,@p1='2015-02-07 21:36:30.313',@p2=173990,@p3=2,@p4='2015-02-07 21:35:32.830'
致:
这样更容易理解
该页面上的控制台应用程序可通过以下方式使用:传递文件参数或复制剪贴板中的sp_executesql
,运行应用程序,然后从剪贴板粘贴生成的SQL
更新:
还可以将SQL格式化程序添加到该解决方案中,以提高可读性:
我在寻找类似的东西,所以我在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();
}
}
void Main()
{
ConvertSql(System.Windows.Forms.Clipboard.GetText()).Dump();
}
私有静态字符串转换SQL(字符串origSql)
{
字符串tmp=origSql.Replace(“”,“~~”);
字符串baseSql;
字符串类型;
字符串paramData=“”;
int i0=tmp.IndexOf(“”)+1;
int i1=tmp.IndexOf(“'”,i0);
如果(i1>0)
{
baseSql=tmp.Substring(i0,i1-i0);
i0=tmp.IndexOf(“'”,i1+1);
i1=tmp.IndexOf(“'”,i0+1);
如果(i0>0&&i1>0)
{
paramTypes=tmp.Substring(i0+1,i1-i0-1);
paramData=tmp.子串(i1+1);
}
}
其他的
{
抛出新异常(“无法在第一个参数中标识SQL语句”);
}
baseSql=baseSql.Replace(“~~”,“');
如果(!String.IsNullOrEmpty(paramData))
{
字符串[]paramList=paramData.Split(“,”.ToCharArray());
foreach(paramList中的字符串paramValue)
{
int iEq=paramValue.IndexOf(“=”);
如果(iEq<0)
继续;
字符串pName=paramValue.Substring(0,iEq.Trim();
string pVal=paramValue.Substring(iEq+1.Trim();
baseSql=baseSql.ReplaceWholeWord(pName,pVal);
}
}
返回baseSql;
}
公共静态类StringExtensionsMethods
{
///
///替换整个单词。
///
///s。
///这个词。
///替代品。
///绳子。
公共静态字符串替换wholeword(此字符串s、字符串字、字符串替换)
{
var firstLetter=word[0];
var sb=新的StringBuilder();
var PreviousWasletterDigit=false;
var i=0;
而(ii+word.Length)
{
if(Char.isleterordigit(s[i+word.Length]))
wholeWordFound=false;
}
某人追加(wholeWordFound?替换:word);
i+=字长;
}
如果(wordFound)继续;
previousWasLetterOrDigit=Char.IsleterOrdigit(c);
sb.附加(c);
i++;
}
如果(s.长度-i>0)
sb.追加(s.子字符串(i));
使某人返回字符串();
}
}
我花了一点时间,创建了Matt Roberts/Wangzq解决方案的一个小修改,没有声明部分,您可以在或上尝试
输入:
exec sp_executesql N'UPDATE MyTable SET [Field1] = @0, [Field2] = @1',N'@0 nvarchar(max) ,@1 int',@0=N'String',@1=0
输出:
UPDATE MyTable SET [Field1] = N'String', [Field2] = 0
代码:
使用系统;
使用System.Linq;
使用System.Text.RegularExpressions;
公共课程
{
公共静态void Main()
{
var sql=@“exec sp_executesql N'updatemytable SET[Field1]=@0,[Field2]=@1',N'@0 nvarchar(max),@1 int',@0=N'String',@1=0”;
Console.WriteLine(ConvertSql(sql));
}
公共静态字符串转换SQL(字符串origSql)
{
var re=new Regex(@“exec*\s*sp\u executesql\s+N'([\s\s]*),\s*N'(@[\s\s]*?),\s*([\s\s]*)”,RegexOptions.IgnoreCase);//1:sql,2:declare,3:setting
变量匹配=重新匹配(origSql);
如果(匹配成功)
{
var sql=match.Groups[1]。Value.Replace(“”,““”);
//var declare=match.Groups[2]。值;
变量设置=match.Groups[3]。值+',';
//要处理变量值中的逗号或单引号,可以使用变量名进行拆分
var re2=新正则表达式(@“@[^',]*?\s*=”);
var variables=re2.Matches(setting).Cast().Select(m=>m.Value).ToArray();
v
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();
}
}
exec sp_executesql N'UPDATE MyTable SET [Field1] = @0, [Field2] = @1',N'@0 nvarchar(max) ,@1 int',@0=N'String',@1=0
UPDATE MyTable SET [Field1] = N'String', [Field2] = 0
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.";
}
}
class Program
{
const string query = "query";
const string decls = "decls";
const string sets = "sets";
static void Main(string[] args)
{
try
{
var text = File.ReadAllText(args[0]);
if(string.IsNullOrEmpty(text))
{
Console.WriteLine("File is empty. Try saving it before using the hillbilly sproc decoder");
}
var regex = new Regex(@"exec sp_executesql N'(?<" + query + ">.*)',N'(?<" + decls + ">[^']*)',(?<" + sets + ">.*)", RegexOptions.Singleline);
var match = regex.Match(text);
if(!match.Success || match.Groups.Count != 4)
{
Console.WriteLine("Didn't capture that one. Shit.");
Console.Read();
return;
}
var sb = new StringBuilder();
sb.Append("DECLARE ").AppendLine(match.Groups[decls].Value);
foreach(var set in match.Groups[sets].Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
sb.Append("SET ").AppendLine(set);
sb.AppendLine(match.Groups[query].Value.Replace("''", "'"));
File.WriteAllText(args[0], sb.ToString());
}
catch(Exception ex)
{
Console.WriteLine("S*t blew up, yo");
Console.WriteLine(ex.ToString());
Console.WriteLine("Press a key to exit");
Console.Read();
}
}
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$(function(){
$("#btn-format").on("click", () =>{
var insql = $("#textarea-in").val();
var regex = new RegExp("exec sp_executesql N'(?<command>.+?(?='(,N'$)?))'(,\s*N'(?<types>.+?(?=',))',\s*(?<vals>.+))?");
var groups = insql.replace(/\n|\r/g, "").match(regex).groups;
var outsql = "";
if (groups.types)
{
var types = groups.types.match(/@[^\s]+ \w+(\([\w\d,]+\))?/g);
for (const typeDeclaration of types) {
outsql = outsql + 'declare ' + typeDeclaration + '\n';
}
outsql = outsql + '\n';
for (const setVal of groups.vals.split(',')) {
outsql = outsql + 'set ' + setVal + '\n';
}
outsql = outsql + '\n';
}
$.ajax({
url: 'https://sqlformat.org/api/v1/format',
type: 'POST',
dataType: 'json',
crossDomain: true,
data: {
sql: groups.command, reindent: 1
},
success: (data) => {
outsql = outsql + data.result;
$("#textarea-out").val(outsql);
},
error: () =>{
outsql = outsql + '-- No format happened. See browser console for details \n';
outsql = outsql + groups.command;
$("#textarea-out").val(outsql);
}
});
})
});
</script>
</head>
<body>
<textarea id="textarea-in" style="width: 100%; height: 48%;" class="form-control" placeholder="type 'exec sp_executesql...' here"></textarea>
<br/>
<button id="btn-format">Format</button>
<br/>
<textarea id="textarea-out" style="width: 100%; height: 48%;" class="form-control"></textarea>
</body>