在SELECT查询中查找WHERE子句

时间:2011-12-18 07:30:19

标签: sql sql-server sql-server-2008 sql-server-2005 tsql

我有一个可能有多个SELECT语句的sql文件,我需要做的是找出select语句的WHERE子句,如果有的话。

Select col1,col2
from table t1
where col1=2 and
convert(something)='abc'

作为上述查询的结果,我需要完整的where子句,并且我希望尽可能使它成为通用的(现在可以忽略子查询)。我需要一些指针来启动这个或任何可用的源代码。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

对于没有子查询的语句,我只是从一个简单的算法开始。

首先用一个空格替换所有空格(空格,制表符,换行符等)。

然后找到第一次出现" where "(注意周围的空格) - 这是起点(当然不包括初始空间)。

从那里,找到第一个" order by "" group by " - 这是你的终点。如果该文本不存在,则结束点是字符串本身的结尾。

在伪代码中,它将类似于:

def getWhereClause (query):
    query = query.replaceAll ("[ \t\n]*", " ")
    whereClause = ""
    while query is not "":
        if query.startsWithIgnoreCase (" where "):
            whereClause = "where "
            query = query.substring (7)
            next while
        if query.startsWithIgnoreCase (" order by ") or
        if query.startsWithIgnoreCase (" group by "):
            return whereClause
        if whereClause != "":
            whereClause = whereClause + query.substring (0,1)
        query = query.substring (1)
    return whereClause

这应该涵盖浩大的大多数非子查询查询,并且您可以在结束条件出现时添加更多可能性。

要记住的一件事是,那些文本搜索和操作应该只在引用区域的外部完成。这意味着如果你想要一个正确的解决方案,你需要一个迷你解析器而不是简单的字符串搜索,如伪代码所示。

我提出这个解决方案是一个(相当快速和肮脏)的解决方案,因为它可能完全符合您的需要而没有完整的SQL解析器的复杂性,相信我,是一个微不足道的运动,从痛苦的经历: - )

答案 1 :(得分:1)

如果您将一个查询视为字符串,则可以通过“”将其拆分为标记,然后将每个标记(小写)与“where”进行比较 - 这会告诉您该子句的第一个标记然后查找“顺序”,然后查找“by”或“group”后跟“by”“group”/“order”标记是你的子句结束后的标记(如果没有找到,那么你的子句会延伸到字符串的末尾)。现在将这些标记索引转换为字符串中的字符索引,然后使用子字符串来获取子句:

 String query;
 boolean hasWhere = false;
 boolean hasGroupOrOrder = false;
 String[] query_tokens = query.split(" ");

// ---------- FIRST GET THE TOKENS WHERE THE WHERE CLAUSE AND GROUP BY/ORDER BY START ---- 
// we want to find the tokens in the string where the where clause starts and where the group by/order by begins -- if there isn't one then endToken will remain -1
int startToken = -1;
int endToken = -1;

for(int i = 0; i < query_tokens.length(); i++)
{
    if(!hasWhere)
    {
        if(query[i].toLowerCase().equals("where"))
{
            begin = i;
            hasWhere = true;
}

    } 
    else
    {
        if(!hasGroupOrOrder)
        {
            if(query[i].toLowerCase().equals("group") || query[i].toLowerCase().equals("order"))
                hasGroupOrOrder = true;
        }
        else
        {
            if(query[i].toLowerCase().equals("by"))
            {
                end = i - 1;
            }else
                {
                        hasGroupOrOrder = false;
                }
        }
    }
}

// we now know the tokens necessary for the query, now we turn these into the character indexes that can be used to take the where clause substring from the query string

String whereClause;
int startIndex = 0; 
int endIndex = 0;

// ---------- NOW GET START INDEX OF "WHERE" IN STRING ---- we want to find the beginIndex " " character as the where token starts here
for(int i = 0; i < startToken; i++)
{
        startIndex = String.indexOf(" ", startIndex);
}

startIndex += 1; 
// since the startIndex will refer the " " right before "where" we need to increment this by 1
// if you don't need the "where " you can strip this off as well...

// ---------- NOW GET END INDEX EITHER END OF STRING OR BEFORE WHERE/GROUP BY STARTS ----
if(endToken == -1) 
{
// this is the case when the where clause extends to end of string
    endIndex = query.length() - 1;
}
else
{
    // we want to find the endIndex " " character as the group by / order by starts here
    for(int i = 0; i < endIToken; i++)
    {
        endIndex = String.indexOf(" ", endIndex);
    }
    endIndex -= 1; 
 // since the endIndex will be at the " " before the where by/order by we must reduce this by 1 to be end of where clause
}

// ---------- NOW GET SUBSTRING! ----
whereClause = query.substring(startIndex, endIndex);

答案 2 :(得分:0)

尝试这个。

using System;
using System.Collections.Generic;
using System.Text;

namespace SQLParser
{
    class Program
    {
        static void Main(string[] args)
        {
            /* A complicated statement with WHERE, ORDER BY and IF Clause*/
            var sql1 = @" SELECT Count(*) AS 'hjkhskj'
                            FROM   ABC

                            SELECT DISTINCT xx AS 'kljklj'
                            FROM   XYZ
                            WHERE  a NOT IN (SELECT b
                                                     FROM   RST)
                            ORDER  BY 1

                            BEGIN TRANSACTION

                            DELETE FROM ABC
                            WHERE  a NOT IN (SELECT b
                                                     FROM   XYZ)

                            IF @@ERROR <> 0
                              BEGIN
                                  ROLLBACK TRANSACTION

                                  GOTO GTY
                              END
                            ELSE
                              COMMIT TRANSACTION

                            SELECT DISTINCT x AS 'SRTT jfkfk'
                            FROM   PQR a
                            WHERE  NOT EXISTS (SELECT m
                                               FROM   MYTU u
                                               WHERE  u.x = m)
                            ORDER  BY 1 ";

            /*A simple statement with WHERE clause only */
            var sql2 = @"Select * FROM Person Where Firstname = 'Merin' AND LastName = 'Nakarmi'";

            var sql3 = @"SELECT TOP 100 * FROM master.sys.fn_get_audit_file('\\network\userdata\audifiles$\SQL_AUDIT\SERVER-1\AdventureWorks\*.sql', DEFAULT, DEFAULT) WHERE CONVERT(DATE, event_time) = CONVERT(DATE, GETDATE());";

            Console.WriteLine(ExtractWhereClause(sql1));
            Console.WriteLine(ExtractWhereClause(sql2));
            Console.WriteLine(ExtractWhereClause(sql3));
            Console.ReadLine();
        }

        /* WHERE clause can occur multiple times in a statement. It will start with WHERE clause and usually ends by ORDER BY CLAUSE, GROUP BY CLAUSE or end of statement */
        struct Occurence
        {
            public int Begin { get; set; }  //Beginning of where clause
            public int End { get; set; }    //Ending of where clause

            internal void Clear()
            {
                Begin = 0;
                End = 0;
            }
        }

        static StringBuilder ExtractWhereClause(string query)
        {
            StringBuilder output = new StringBuilder();

            string[] tokens = query.Split(new char[] {' ', '\r','\t','\n' });
            List<string> nonEmptyTokens = new List<string>();
            List<Occurence> Occurences = new List<Occurence>();

            foreach(string s in tokens)
            {
                if (!s.Equals(""))
                    nonEmptyTokens.Add(s);
            }

            Occurence occurence = new Occurence();

            for (int i = 0; i<nonEmptyTokens.Count; i++)
            {
                var currentToken = nonEmptyTokens[i];
                if (currentToken.ToUpper().Contains("WHERE"))
                {
                    if (occurence.Begin == 0)
                        occurence.Begin = i;
                    else 
                        {
                            occurence.End = i - 1;
                            Occurences.Add(occurence);
                            occurence.Clear();
                            occurence.Begin = i;
                        }
                }
                else if (currentToken.ToUpper().Contains("GROUP") || currentToken.ToUpper().Contains("ORDER"))
                {
                    if (nonEmptyTokens[i + 1].ToUpper().Contains("BY"))
                    {
                        if(occurence.Begin != 0 && occurence.End == 0)
                        {
                            occurence.End = i -1;
                            Occurences.Add(occurence);
                            occurence.Clear();
                        }
                    }
                }
                else if (currentToken.ToUpper().Contains("IF"))
                {
                    if (occurence.Begin != 0 && occurence.End == 0)
                    {
                        occurence.End = i - 1;
                        Occurences.Add(occurence);
                        occurence.Clear();
                    }
                }
            }
            //Check for last Where clause without ending
            if(occurence.Begin != 0)
            {
                occurence.End = nonEmptyTokens.Count - 1;
                Occurences.Add(occurence);
                occurence.Clear();
            }


            foreach(Occurence o in Occurences)
            {
                for(int i = o.Begin; i <= o.End; i++)
                {
                    output.Append(nonEmptyTokens[i]);
                    output.Append(" ");
                }
                output.Append("\n");
            }

            return output;
        }
    }
}

输出:

enter image description here

如果您不想在控制台中看到WHERE,请替换occurence.Begin = i;occurence.Begin = i + 1;