我的任务是编写一个将sql查询作为字符串传递的函数,它应该解析此查询,将“tablename”添加到它找到的任何表中。我给了一些代码作为例子(它只是寻找“from”和“where / inner / outer / left / right”等实例。并假设中间的单词是一个表... 这是在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)联合查询
我无法检索该查询中指定的表名
等待您的回复和评论
答案 0 :(得分:3)
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.
答案 1 :(得分:0)
如果我没有正确理解你的问题,请回复我。
针对您的数据库运行以下查询
SELECT * FROM information_schema.tables
检索表名并附加它。