using System; using System.Collections.Generic; using System.Text; namespace CYQ.Data.SQL { /// /// SQL语法解析规则 /// internal class SqlSyntax { /// /// 分析语法 /// public static SqlSyntax Analyze(string sql) { return new SqlSyntax(sql); } public string SqlText; private SqlSyntax(string sql) { SqlText = sql; FormatSqlText(sql); } public string TableName = string.Empty; public string Where = string.Empty; public bool IsInsert = false; public bool IsInsertInto = false; public bool IsSelect = false; public bool IsUpdate = false; public bool IsDelete = false; public bool IsFrom = false; public bool IsGetCount = false; // bool IsAll = false; public bool IsTopN = false; public bool IsDistinct = false; public bool IsLimit = false; public bool IsOffset = false; public bool IsWhere = false; public bool IsOrder = false; public int TopN = -1; public int PageIndex = 0; public int PageSize = 0; public List FieldItems = new List(); void FormatSqlText(string sqlText) { string[] items = sqlText.Split(' '); foreach (string item in items) { #region MyRegion switch (item.ToLower()) { case "insert": IsInsert = true; break; case "into": if (IsInsert) { IsInsertInto = true; } break; case "select": IsSelect = true; break; case "update": IsUpdate = true; break; case "delete": IsDelete = true; break; case "from": IsFrom = true; break; case "count(*)": case "count(0)": case "count(1)": IsGetCount = true; break; case "limit": if (IsSelect && (IsFrom || IsWhere)) { IsLimit = true; } break; case "offset": if (IsLimit) { IsLimit = false; IsOffset = true; } break; case "order": if (IsFrom || IsWhere) { IsOrder = true; } break; case "by": case "where": if (IsFrom || IsUpdate) { IsFrom = false; IsWhere = true; int startIndex = sqlText.LastIndexOf(" " + item + " ") + item.Length + 2; int limit = sqlText.IndexOf(" limit ", startIndex, StringComparison.OrdinalIgnoreCase); if (limit == -1) { Where = sqlText.Substring(startIndex); } else { Where = sqlText.Substring(startIndex, limit - startIndex); } if (item.ToLower() == "by") { Where = "order by " + Where; } } break; case "top": if (IsSelect && !IsFrom) { IsTopN = true; } break; case "distinct": if (IsSelect && !IsFrom) { IsDistinct = true; } break; case "set": if (IsUpdate && !string.IsNullOrEmpty(TableName) && FieldItems.Count == 0) { #region 解析Update的字段与值 int start = sqlText.IndexOf(item) + item.Length; int end = sqlText.ToLower().IndexOf("where"); string itemText = sqlText.Substring(start, end == -1 ? sqlText.Length - start : end - start); int quoteCount = 0, commaIndex = 0; for (int i = 0; i < itemText.Length; i++) { if (i == itemText.Length - 1) { string keyValue = itemText.Substring(commaIndex).Trim(); if (!FieldItems.Contains(keyValue)) { FieldItems.Add(keyValue.Trim()); } } else { switch (itemText[i]) { case '\'': quoteCount++; break; case ',': if (quoteCount % 2 == 0)//双数,则允许分隔。 { string keyValue = itemText.Substring(commaIndex, i - commaIndex).Trim(); if (!FieldItems.Contains(keyValue)) { FieldItems.Add(keyValue); } commaIndex = i + 1; } break; } } } #endregion } break; default: if (IsOffset) { if (!int.TryParse(item, out PageIndex)) { PageIndex = 0; } } else if (IsLimit) { if (!int.TryParse(item, out PageSize)) { PageSize = 0; } } if (!IsWhere) { if (IsTopN && TopN == -1) { if (int.TryParse(item, out TopN))//查询TopN { PageSize = TopN; } IsTopN = false;//关闭topN } else if ((IsFrom || IsUpdate || IsInsertInto) && string.IsNullOrEmpty(TableName)) { TableName = item.Split('(')[0].Trim();//获取表名。 } else if (IsSelect && !IsFrom)//提取查询的中间条件。 { #region Select 字段搜集 switch (item) { case "*": case "count(*)": case "count(0)": case "count(1)": case "distinct": break; default: fieldText.Append(item + " "); break; } #endregion } else if (IsInsertInto && !string.IsNullOrEmpty(TableName) && FieldItems.Count == 0) { #region 解析Insert Into的字段与值 int start = sqlText.IndexOf(TableName) + TableName.Length; int end = sqlText.IndexOf("values", start, StringComparison.OrdinalIgnoreCase); if (end == -1) { end = sqlText.IndexOf("select", start, StringComparison.OrdinalIgnoreCase); if (end == -1) { break; } } string keys = sqlText.Substring(start, end - start).Trim(); string[] keyItems = null;//insert into aaa values('',''); if (keys.Length > 2)//可能为空。 { keyItems = keys.Substring(1, keys.Length - 2).Split(',');//去除两边括号再按逗号分隔。 } string values = sqlText.Substring(end + 6).Trim(); if (IsSelect && IsFrom) { end = values.IndexOf("from"); if (end > 0) { //insert into ...select ...from 模式 values = values.Substring(0, end);//去除两边括号 } } else { // insert into ... values 模式。 values = values.Substring(1, values.Length - 2);//去除两边括号 } if (keyItems == null) { keyItems = new string[values.Split(',').Length]; } int quoteCount = 0, commaIndex = 0, valueIndex = 0; #region get values for (int i = 0; i < values.Length; i++) { if (valueIndex >= keyItems.Length) { break; } if (i == values.Length - 1) { string value = values.Substring(commaIndex).Trim(); keyItems[valueIndex] += "=" + value; } else { switch (values[i]) { case '\'': quoteCount++; break; case ',': if (quoteCount % 2 == 0)//双数,则允许分隔。 { string value = values.Substring(commaIndex, i - commaIndex).Trim(); keyItems[valueIndex] += "=" + value; commaIndex = i + 1; valueIndex++; } break; } } } #endregion FieldItems.AddRange(keyItems); #endregion } } break; } #endregion } #region Select 字段解析 if (fieldText.Length > 0) { if (FieldItems.Count == 0) { string[] fields = fieldText.ToString().Split(','); foreach (string item in fields) { FieldItems.Add(item.Trim()); } } fieldText.Length = 0; } #endregion } private StringBuilder fieldText = new StringBuilder(); } }