मैं एक ही समस्या का समाधान ढूंढ रहा था, लेकिन कोई उपयुक्त नहीं मिला (एसएमओ का उपयोग मेरे मामले में स्वीकार्य नहीं था)। तो, मुझे अपना पार्सर लिखना पड़ा।यहां यह है:
static IEnumerable<string> ParseSqlBatch(Stream s)
{
if (s == null)
throw new ArgumentNullException();
StringBuilder sbSqlStatement = new StringBuilder();
Stack<string> state = new Stack<string>();
StreamReader sr = new StreamReader(s);
//initially search for "GO" or open tag of strings ('), comments (--, /*) or identifiers ([)
string pattern = @"(?>(?<=^\s*)go(?=\s*(--.*)?$)|''(?!')|(?<!')'|(?<!\[)\[|--(?=.*)?|/\*)";
//if open tag found search for close tag, then continue search
string patternCloseString = @"(?>''|'(?!'))";
string patternCloseIdentifier = @"(?>\]\]|\](?!\]))";
string patternComments = @"(?>\*/|/\*)";
Regex rx = new Regex(pattern, RegexOptions.IgnoreCase);
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
int ix = 0;
bool bBreak = false;
while (ix < line.Length && !bBreak)
{
Match m = rx.Match(line, ix);
if (!m.Success)
{
sbSqlStatement.Append(line.Substring(ix));
break;
}
int ix2 = m.Index;
string word = m.Value;
sbSqlStatement.Append(line.Substring(ix, ix2 - ix));
if (state.Count == 0)
{
if (string.Compare(word, "GO", true) == 0)
{
if (sbSqlStatement.Length > 0)
{
yield return sbSqlStatement.ToString();
sbSqlStatement = new StringBuilder();
break;
}
}
else
{
switch (word)
{
case "'":
rx = new Regex(patternCloseString);
break;
case "[":
rx = new Regex(patternCloseIdentifier);
break;
case "/*":
rx = new Regex(patternComments);
break;
case "--":
sbSqlStatement.Append(line.Substring(ix2));
bBreak = true;
continue;
}
if (word != "''")
state.Push(word);
}
}
else
{
string st = state.Peek();
switch (st)
{
case "'":
if (st == word)
state.Pop();
break;
case "[":
if (word == "]")
state.Pop();
break;
case "/*":
if (word == "*/")
state.Pop();
else if (word == "/*")
state.Push(word);
break;
}
if (state.Count == 0)
rx = new Regex(pattern, RegexOptions.IgnoreCase);
}
ix = ix2 + word.Length;
sbSqlStatement.Append(word);
}
sbSqlStatement.AppendLine();
}
if (sbSqlStatement.Length > 0)
yield return sbSqlStatement.ToString();
}
यह सही ढंग से तारों, पहचानकर्ताओं और टिप्पणियों के भीतर "जाओ" को संभालता है। शायद आदर्श नहीं है, लेकिन सैकड़ों विभिन्न .sql स्क्रिप्ट पर सफलतापूर्वक परीक्षण किया गया।
और फिर, उदाहरण के लिए:
using (FileStream fs = new FileStream("SampleBatch.sql", FileMode.Open, FileAccess.Read))
{
foreach (string statement in ParseSqlBatch(fs))
{
//execute statement here, or do something with it
}
fs.Close();
}
मुझे आशा है कि यह किसी को मदद मिलेगी।
स्रोत
2013-06-26 11:46:52
चीज़ ... यह एक लागत 12k http: //www.temporal-wave .com/index.php? विकल्प = com_content & view = आलेख और आईडी = 48: sqlparser और catid = 35: उत्पादों और itemid = 53 –
नोट: माइक्रोसॉफ्ट एक टीएसक्यूएल 100 पार्सर जहाज ... लेकिन मेरे जीवन के लिए मैं यह नहीं समझ सकता कि इसे बैच के साथ कैसे प्रदान किया जाए पहचानकर्ता ... मैं बहुत ही सीमित समाधान के बावजूद बस एक छोटा सा करने की ओर झुक रहा हूं। –