【问题标题】:Getting table name from query through c# .net通过c#.net从查询中获取表名
【发布时间】:2013-05-17 04:12:21
【问题描述】:

我的任务是编写一个函数,该函数将作为字符串传递一个 sql 查询,它应该在它找到的任何表之前解析这个查询。我已经给出了一些代码作为示例(它只是寻找“来自”和“哪里/内部/外部/左/右”等的实例......并假设中间的单词是一个表格...... 这是在 C# 中完成的

我真正要寻找的只是最好的方法的指针......(虽然简短的是我将传递一个字符串并返回一个字符串,所以如果您有任何想法,请记住这一点! )

我已经尝试使用 Sql 解析器来处理以下示例查询,但它对我没有帮助

  //"SELECT e.last_name,       e.department_id,       d.department_name FROM   employees e       LEFT OUTER JOIN department d         ON ( e.department_id = d.department_id ); "
   //"SELECT   a.Id, a.Name  AS Surname, b.preName, c.Busrel_Id FROM  Customer a  LEFT JOIN CustomerDetail b ON a.Id = b.fId   LEFT JOIN Businessrel c            ON b.cId = c.Bid         JOIN Contract d           ON c.Id = d.fId  AND a.DATE < '20071204:13.23.14.000' AND a.cst_Class_cd IN ('01','02') AND b.Name LIKE 'W%'  AND (SELECT MAX(e.TIMESTAMP) FROM   dDate e  WHERE  e.colLid = a.Id) ORDER BY a.Name, b.preName";
     //SELECT   Quantity,b.Time,c.Description FROM   (SELECT ID,Time FROM bTab) b  INNER JOIN aTab a on a.ID=b.ID  INNER JOIN cTab c on a.ID=c.ID

我使用的代码是

using gudusoft.gsqlparser;
using gudusoft.gsqlparser.Units;

TSelectSqlStatement stmt = (TSelectSqlStatement)sqlparser.SqlStatements[0];
                foreach (TLzField lcfield in stmt.Fields)
                {
                    lctablename = "NULL";
                    lcfieldalias = "NULL";   

                    if (lcfield.FieldPrefix.Length > 0)
                    {
                        lctablename = findtablename(stmt.Tables, lcfield.FieldPrefix);
                    }

                    lcfieldname = lcfield.FieldName;

                    if (lcfield.FieldAlias.Length > 0)
                    {
                        lcfieldalias = lcfield.FieldAlias;
                    }

                    Console.WriteLine("{0},{1},{2}", lctablename, lcfieldname, lcfieldalias);
                }

public static string findtablename(TLzTableList tbl, string tname)
        {
            foreach (TLzTable tb in tbl)
            {
                if (tb.TableName.CompareTo(tname) == 0)
                {
                    return tb.TableName;
                }
                else if (tb.TableAlias.CompareTo(tname) == 0)
                {
                    return tb.TableName;
                }
            }
            return tname;
        }

列出的查询是什么,例如

1) 嵌套查询 2)子查询 3)联合查询

我无法检索该查询中指定的表名

等待您的回复和cmets

【问题讨论】:

    标签: c# .net regex xml-parsing sql-parser


    【解决方案1】:

    SQL 解析器似乎是更好的解决方案,但我想我还是会尝试编写一个正则表达式。此正则表达式检测您提供的示例字符串中的所有表名。这有点混乱,当然有可能存在此正则表达式未涵盖的情况。它必须与 IgnoreCase 选项一起使用。

    (?<=(?:FROM|JOIN)[\s(]+)(?>\w+)(?=[\s)]*(?:\s+(?:AS\s+)?\w+)?(?:$|\s+(?:WHERE|ON|(?:LEFT|RIGHT)?\s+(?:(?:OUTER|INNER)\s+)?JOIN)))
    

    这是一段示例代码,所有表名都以“dbo”为前缀。

    const string REGEX_MATCH_TABLE_NAME = @"(?<=(?:FROM|JOIN)[\s(]+)(?>\w+)(?=[\s)]*(?:\s+(?:AS\s+)?\w+)?(?:$|\s+(?:WHERE|ON|(?:LEFT|RIGHT)?\s+(?:(?:OUTER|INNER)\s+)?JOIN)))";
    string testInput = "SELECT e.last_name,e.department_id, d.department_name FROM   employees e LEFT OUTER JOIN department d ON ( e.department_id = d.department_id );";
    string resultString = Regex.Replace(testInput, REGEX_MATCH_TABLE_NAME, "dbo.$0", RegexOptions.IgnoreCase | RegexOptions.Multiline);
    

    这里是正则表达式的粗略细分:

    (?<=                #Begin positive lookbehind.
        (?:FROM|JOIN)   #Match keywords that usually preceed a table name.
        [\s(]+
    )                   #End positive lookbehind.
    (?>\w+)             #Match the table name. Atomic for faster failed matches.
    (?=                 #Begin positive lookahead.
        [\s)]*
        (?:\s+(?:AS\s+)?\w+)?                                               #Match the table alias that possibly follows the table name.
        (?:$|\s+(?:WHERE|ON|(?:LEFT|RIGHT)?\s+(?:(?:OUTER|INNER)\s+)?JOIN)) #Match keywords that usually follow a table name.
    )                   #End positive lookahead.
    

    【讨论】:

    • 嗨,如果我使用没有连接的查询,但在 from (select * from tableA, tableB where tableA.ID = tableB.ID) 之后放置表,则正则表达式不起作用。在那种情况下我该怎么办?谢谢。
    【解决方案2】:

    如果我没有正确理解您的问题,请回复我。

    对您的数据库运行以下查询,

     SELECT * FROM information_schema.tables
    

    检索表名并附加它。

    【讨论】:

    • 让我们考虑一下你没有连接相关属性的情况,只有你有一个命令,例如:select * from table1 我只需要从上面的命令中获取表
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    相关资源
    最近更新 更多