2011-02-25 25 views
3

我需要在SQL字符串中查找实际外部'from'的索引。这里有一些SQL字符串的例子,我会查找实际的FROM:查找SQL语句字符串中的外部FROM子句的索引

select * from table --easy 
select *, (select top 1 col1 from anothertable) as col1 from table 
select * from table, (select col1 from anothertable) as anothertable 
select * from table where col1=(select top 1 col1 from anothertable) 

我确定有更多有效的SQL语句使用子选择。我认为我需要的是一个正则表达式或解析器,它知道最外层的'from'和不同的'from'之间的区别。当然,我可能没有考虑找到外部'from'的其他陷阱,所以任何输入都将被赞赏。

回答

0

假设您想要查找的“from”是唯一一个括号外的字符,您可以逐字通过字符串并计算括号(打开时为+1,关闭时为-1)。当你的支架计数器为0时发现“from”,它应该是正确的。

+0

哇,太简单了!谢谢。 – sagesmith7 2011-02-26 02:39:34

+1

@ sagesmith7 - 只要您的查询没有任何包含括号或表格名称的注释,例如'[non standard :-)]'或者可能有很多其他边缘案例! – 2011-02-26 11:38:01

4

您可以使用Microsoft.Data.Schema.ScriptDom。概念应用的边缘粗糙。

using System; 
using System.Collections.Generic; 
using System.IO; 
using Microsoft.Data.Schema.ScriptDom; 
using Microsoft.Data.Schema.ScriptDom.Sql; 

namespace ConsoleApplication1 
{ 
    internal class Program 
    { 
     public static void Main(string[] args) 
     { 
      string[] queries = 
       { 
        @"select * from table1;", 
        /*Test multiline*/ 
        @"select *, 
           (select top 1 col1 from anothertable) as col1 from table1;" 
        , 
        @"select * from table1, (select col1 from anothertable) as anothertable;", 
        @"select * from table1 where col1=(select top 1 col1 from anothertable)", 
        /*Test invalid syntax ("table" is a reserved word)*/ 
        @"select * from table where col1=(select top 1 col1 from anothertable)" 
       }; 

      foreach (string query in queries) 
      { 
       Parse(query); 
      } 

      Console.ReadKey(); 
     } 

     private static void Parse(string query) 
     { 
      Console.WriteLine(@"------------------------------------------"); 
      Console.WriteLine(@"Parsing statement ""{0}""", query); 

      var parser = new TSql100Parser(false); 

      IList<ParseError> errors; 
      IScriptFragment result = parser.Parse(new StringReader(query), out errors); 

      if (errors.Count > 0) 
      { 
       Console.WriteLine(@"Errors encountered: ""{0}""", errors[0].Message); 
       return; 
      } 


      TSqlStatement statement = ((TSqlScript) result).Batches[0].Statements[0]; 

      if (statement is SelectStatement) 
      { 
       TableSource tableSource = (((QuerySpecification)((SelectStatement)statement).QueryExpression).FromClauses[0]); 

       Console.WriteLine(@"Top level FROM clause at Line {0}, Column {1} (Character Offset {2})", 
            tableSource.StartLine, tableSource.StartColumn, tableSource.StartOffset); 
       Console.WriteLine(); 
       Console.WriteLine(); 

      } 
     } 
    } 
} 

输出

------------------------------------------ 
Parsing statement "select * from table1;" 
Top level FROM clause at Line 1, Column 15 (Character Offset 14) 


------------------------------------------ 
Parsing statement "select *, 
           (select top 1 col1 from anothertable) as col1 from 
table1;" 
Top level FROM clause at Line 2, Column 82 (Character Offset 93) 


------------------------------------------ 
Parsing statement "select * from table1, (select col1 from anothertable) as ano 
thertable;" 
Top level FROM clause at Line 1, Column 15 (Character Offset 14) 


------------------------------------------ 
Parsing statement "select * from table1 where col1=(select top 1 col1 from anoth 
ertable)" 
Top level FROM clause at Line 1, Column 15 (Character Offset 14) 


------------------------------------------ 
Parsing statement "select * from table where col1=(select top 1 col1 from anothe 
rtable)" 
Errors encountered: "Incorrect syntax near table." 
0

考虑到,从可以选择子句为SP的字段名,别名或名称中occure,以及。 如果TABLE从字段中选择,则从select中选择TABLE是有效的。