Поиск индекса внешнего предложения FROM в строке оператора SQL - PullRequest
3 голосов
/ 26 февраля 2011

Мне нужно найти индекс фактического внешнего 'from' в строке SQL. Вот несколько примеров строк SQL, которые я бы искал для фактического ОТ:

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, которые используют подвыборы. Я думаю, что мне нужно регулярное выражение или синтаксический анализатор, который знает разницу между самым внешним «от» и пропускает любые подпрограммы «от». Конечно, я, возможно, не рассматриваю другие подводные камни для поиска внешнего «от», поэтому любой вклад будет оценен.

Ответы [ 3 ]

4 голосов
/ 26 февраля 2011

Вы можете использовать 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 голосов
/ 04 июля 2013

Примите во внимание, что from может также встречаться в предложении select в качестве имени поля, псевдонима или имени SP. Например, выбор из выбора из таблицы TABLE действителен, если в TABLE есть поле из.

0 голосов
/ 26 февраля 2011

Предполагая, что «from», которое вы хотите найти, является единственным за пределами скобок, вы можете пройти строку через строку и посчитать скобки (+1 при открытии, -1 при закрытии).Когда вы находите «from», когда ваш счетчик скобок равен 0, он должен быть правильным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...