我想解析存储在日志数据库中的一些SQL查询 - 我不想将它们提交给SQL数据库,只是为了提取SELECT和WHERE子句中使用的字段。Perl SQL :: Parser表别名替换:适用于SELECT列名但不适用于WHERE列名
我一直在处理Java,Python和Perl中的几个SQL解析器。似乎对我的问题更好地工作的是SQL :: Parser和SQL :: Statement。有了这些我能写出下面的代码:
#!/usr/bin/perl
use strict;
use SQL::Parser;
use SQL::Statement;
use Data::Dumper;
my $sql = "SELECT sl.plate,sp.fehadop FROM sppLines AS sl ".
"JOIN sppParams AS sp ON sl.specobjid = sp.specobjid ".
"WHERE fehadop < -3.5 ";
my $parser = SQL::Parser->new();
my $stmt = SQL::Statement->new($sql,$parser);
printf("COMMAND [%s]\n",$stmt->command);
printf("COLUMNS \n");
my @columns = @{$stmt->column_defs()};
foreach my $column (@columns)
{
print " ".$column->{value}."\n";
}
printf("TABLES \n");
my @tables = $stmt->tables();
foreach my $table (@tables)
{
print " ".$table->{name}."\n";
}
printf("WHERE COLUMNS\n");
my $where_hash = $stmt->where_hash();
print Dumper($where_hash);
很抱歉,如果实在是太长了,它是最小的,自包含的例子,我可以想出。
这段代码的输出是:
COMMAND [SELECT]
COLUMNS
spplines.plate
sppparams.fehadop
TABLES
spplines
sppparams
WHERE COLUMNS
$VAR1 = {
'arg1' => {
'value' => 'fehadop',
'type' => 'column',
'fullorg' => 'fehadop'
},
'op' => '<',
'nots' => {},
'arg2' => {
'str' => '-?0?',
'fullorg' => '-3.5',
'name' => 'numeric_exp',
'value' => [
{
'fullorg' => '3.5',
'value' => '3.5',
'type' => 'number'
}
],
'type' => 'function'
},
'neg' => 0
};
解析器返回列已经与真实的表的名称(如spplines更名为 .plate不是名称(通过对$stmt->column_defs()
调用获得) s1 .plate) - 这就是我想要的。
我也想要在WHERE
子句中使用的列的名称。 我已经知道如何递归地解析$stmt->where_hash()
的结果(不包括使帖子清晰的代码),但即使从转储其内容,我也可以看到列名与表没有关联。
我想确保WHERE
子句中的列名称前面还有表名称。解析$stmt->where_hash()
的结果后,我会得到sppparams.fehadop而不是fehadop。
这可能与SQL :: Parser?
感谢 (大编辑 - 试图使问题更清晰)
您能否以更清晰的方式添加预期的输出?问题的下半部分有点喋喋不休。 – simbabque
我编辑了这个问题,希望它更清晰。 –