最近在做公司的查詢平臺,要抓以前舊的SQL語句。用VS抓出來的語句經常是一些沒有分段的一連串的SQL,複製到SQL SERVER 2008後還要自己分段,相當麻煩。於是就有了寫一個簡單的SQL格式化工具的想法。
我的實現思路很簡單:
1 設置一個SQL語句每一段的長度值,超過這個長度值的時候就給他增加一個分段符。
代碼:
public partial class Form1 : Form
{
//用於標記切割時的開始位置
int stratNum=0;
string temp;
//設置格式化後每一段SQL語句的長度值
int length = 40;
StringBuilder sb;
public Form1()
{
InitializeComponent();
}
private void btnFormat_Click(object sender, EventArgs e)
{
try
{
//字符長度
label1.Text = Convert.ToString(tbSourceSql.Text.Length);
sb = new StringBuilder();
while (stratNum <= (tbSourceSql.Text.Length))
{
//判斷是否到最後一行
if ((tbSourceSql.Text.Length - stratNum) > length)
{
//判斷結尾是否爲空字符串或標點
temp = tbSourceSql.Text.Substring(stratNum, length);
// 如果不是以“ ”或“,”結尾,則重新截取
while(!(temp.EndsWith(" ") || temp.EndsWith(",")))
{
length++;
temp = tbSourceSql.Text.Substring(stratNum, length);
}
stratNum += length;
}
else
{
temp = tbSourceSql.Text.Substring(stratNum);
stratNum += length;
}
sb.Append(temp + Environment.NewLine);
}
tbFormatSql.Text = sb.ToString();
MessageBox.Show("Format Success.");
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
stratNum = 0;
sb = null;
}
}
}
實現語句相當簡單,但好像效果不是很好。因爲有些會行會超出設置的長度。以後再細查原因。
效果:
需要分割的SQL語句:
SELECT distinct PLActorRight.*,PLMenuItem.PLMenuName,PLMenuItem.PLMenuStep,PLMenuItem.PLMenuValue,PLMenuItem.PLSystemID,PLMenuItem.PLAssemblyName,PLMenuItem.PLClassName,PLActorIDSystemID=PLMenuItem.PLSystemID*100000 + PLActorRight.PLActorID FROM PLActorRight LEFT JOIN PLMenuItem ON PLMenuItem.PLMenuID=PLActorRight.PLMenuID WHERE PLActorID IN (SELECT PLActorID FROM PLUserActor WHERE <<PLUserID ={0}>> AND PLActorRight.PLEnabledFlag=1 AND PLActorRight.PLShowFlag=1)
格式化後效果圖:
2 設置幾個SQL的關鍵字。遇到關鍵字就分段。
代碼:
public partial class Form1 : Form
{
//分割字段
string[] keyString = new string[] { "FROM", "LEFT JOIN", "RIGHT JOIN", "INNER JOIN", "ORDER BY", "GROUP BY", "SELECT", "UNION ALL" };
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 給關鍵字加分割符
/// </summary>
/// <param name="oldString"></param>
/// <returns></returns>
private string[] GetNewString(string[] oldString)
{
string[] newString = new string[oldString.Length];
for (int i = 0; i < newString.Length; i++)
{
newString[i] +=oldString[i]+ Environment.NewLine;
}
return newString;
}
private void btnFormat2_Click(object sender, EventArgs e)
{
string sourceSql = this.tbSourceSql.Text;
string reString= ReplaceStrings(sourceSql, keyString, GetNewString(keyString));
this.tbFormatSql.Text = reString.ToString();
}
private string ReplaceStrings(string str,string[] oldStrings,string[] newStrings)
{
//Length取數據長度較短的那個
string reString = string.Empty;
int length = oldStrings.Length > newStrings.Length ? newStrings.Length : oldStrings.Length;
for (int i = 0; i < length; i++)
{
string tempString = string.Empty;
//替換
tempString = str.Replace(oldStrings[i], newStrings[i]);
str = tempString;
}
return str;
}
}
同樣的原SQL代碼,分割後效果圖:
兩個都是很粗略的方法,要想做出格式很好的SQL語句,還有很多要做。比如方法2中最好加一個長度限定,要了一定長度後自動分割。以及自動維護分割的關鍵字等。