从任何SQL查询中提取列名和表名字符串
本文关键字:字符串 提取 任何 SQL 查询 | 更新日期: 2023-09-27 18:16:49
假设我有一个这样的SQL查询:
SELECT c_mandant,
hist_datum,
parkey1,
parkey2,
funktionscode,
ma_parkey,
me_parkey ,
CASE
WHEN EXISTS
(
SELECT 1
FROM cds_h_gruppe GRP1
WHERE grp1.c_mandant = c_mandant
AND grp1.hist_datum = Add_months(Last_day(Trunc(sysdate)), -1)
AND grp1.funktionscode = 'H'
AND grp1.parkey1 = ma_parkey
) THEN 1
ELSE NULL
END ma_me ,
CASE
WHEN EXISTS
(
SELECT 1
FROM cds_h_gruppe GRP2
WHERE grp2.c_mandant = c_mandant
AND grp2.hist_datum = Add_months(Last_day(Trunc(sysdate)), -1)
AND grp2.funktionscode = 'U'
AND grp2.parkey1 = me_parkey
) THEN 1
ELSE NULL
END me_ma,
Row_number() OVER (partition BY c_mandant, ma_parkey, me_parkey ORDER BY c_mandant, ma_parkey, me_parkey) anz_ma
FROM
(
SELECT c_mandant,
hist_datum,
parkey1,
parkey2,
funktionscode ,
CASE
WHEN funktionscode = 'U' THEN parkey1
ELSE parkey2
END ma_parkey ,
CASE
WHEN funktionscode = 'U' THEN NULL
ELSE parkey1
END me_parkey
FROM cds_h_gruppe
WHERE funktionscode IN ('U',
'H')
AND hist_datum = Add_months(Last_day(Trunc(sysdate)), -1)
我想从查询中提取表名和列名。结果应该类似于
表:
CDS_H_GRUPPE
列:
CDS_H_GRUPPE.c_mandant
CDS_H_GRUPPE.funktionscode
CDS_H_GRUPPE.hist_datum
CDS_H_GRUPPE.parkey1
CDS_H_GRUPPE.parkey2
我可以从任何复杂的查询字符串中提取列名和表名,这对Oracle, SQL server或DB2有效吗?
不要尝试自己解析它,使用SQL解析器。显然,实体框架曾经有一个,但不再有了。似乎还有更多的,比如这个来自讽刺项目。
有一个商业解析器,你可以花900美元(如果你想公开发布你的代码,就得花1900美元)。
在c#中Lexing partial SQL
我想你可能可以使用SqlParser 'Carbunql'来做。
https://github.com/mk3008/Carbunql例如,可以通过如下方式获取select子句信息:
using Carbunql;
var sq = new SelectQuery(@"SELECT c_mandant, hist_datum, ...");
Console.WriteLine("columns");
sq.SelectClause!.Items.ForEach(item =>
{
Console.Write(" Alias : " + item.Alias);
Console.Write(", Type : " + item.Value.GetType().Name);
if (item.Value is ColumnValue c)
{
Console.Write(", Table : " + c.TableAlias);
Console.Write(", Column : " + c.Column);
}
Console.WriteLine();
});
执行结果如下所示:
columns
Alias : c_mandant, Type : ColumnValue, Table : , Column : c_mandant
Alias : hist_datum, Type : ColumnValue, Table : , Column : hist_datum
Alias : parkey1, Type : ColumnValue, Table : , Column : parkey1
Alias : parkey2, Type : ColumnValue, Table : , Column : parkey2
Alias : funktionscode, Type : ColumnValue, Table : , Column : funktionscode
Alias : ma_parkey, Type : ColumnValue, Table : , Column : ma_parkey
Alias : me_parkey, Type : ColumnValue, Table : , Column : me_parkey
Alias : ma_me, Type : CaseExpression
Alias : me_ma, Type : CaseExpression
Alias : anz_ma, Type : FunctionValue
虽然粗略的信息可以很容易地获得,但需要详细地获取引用的表和列名。
这里有一些需要改进的地方。
·在SQL语句的SELECT子句中指定表名可以从from子句中进行推断,但是显式地声明
会更安全。例子select t.c_mandant from CDS_H_GRUPPE as t
·计算公式需要递归分析"c_mandant"被解析为ColumnValue类,因此很容易获得列名,但您需要找出其他类在内部引用的列。
·需要从表别名到表的反向查找ColumnValue类可以获取表的别名,而不是表名。需要从别名到表的反向查找。但是,如果在FROM子句中指定了子查询,则必须递归解析子查询以查找物理表名。