我在文本文件中有一系列select语句,我需要从每个select查询中提取字段名称。如果某些字段没有使用to_char()
等嵌套函数,那么这将很容易。
给定select语句字段可以有几个嵌套括号,如:
ltrim(rtrim(to_char(base_field_name, format))) renamed_field_name,
或仅仅base_field_name
作为字段的简单情况,Perl中的正则表达式是什么样的?
答案 0 :(得分:11)
不要尝试编写正则表达式解析器(尽管perl regexes 可以处理这样的嵌套模式),使用SQL::Statement::Structure。
答案 1 :(得分:2)
为什么不询问目标数据库本身如何解释查询?
在perl中,可以使用DBI来查询SQL查询的预处理表示。有时这是特定于数据库的:一些驱动程序(在perl DBD::
命名空间下)支持其RDBMS的描述语句的想法,其方式类似于RDBMS的本机C或C ++ API。
但是,一般情况下可以这样做,因为DBI会将结果列的名称放在语句句柄属性NAME
中。例如,以下内容很有可能在任何支持DBI的RDBMS上工作:
use strict;
use warnings;
use DBI;
use constant DSN => 'dbi:YouHaveNotToldUs:dbname=we_do_not_know';
my $dbh = DBI->connect(DSN, ..., { RaiseError => 1 });
my $sth;
while (<>) {
next unless /^SELECT/i; # SELECTs only, assume whole query on one line
chomp;
my $sql = /\bWHERE\b/i ? "$_ AND 1=0" : "$_ WHERE 1=0"; # XXX ugly!
eval {
$sth = $dbh->prepare($sql); # some drivers don't know column names
$sth->execute(); # until after a successful execute()
};
print $@, next if $@; # oops, problem with that one
print join(', ', @{$sth->{NAME}}), "\n";
}
XXX丑陋!位会尝试在SELECT上附加一个始终为false的条件,以便SQL引擎在execute()
时不必执行任何实际操作。这是一种非常天真的方法 - /\bWHERE\b/i
测试不再正确识别SQL WHERE子句,而不是简单的正则表达式正确解析SELECT字段名称 - 但它很可能有效。
答案 2 :(得分:1)
在我使用的办公室有点相关的问题:
my @SqlKeyWordList = qw/select from where .../; # (1)
my @Candidates =split(/\s/,$SqlSelectQuery); # (2)
my %FieldHash; # (3)
for my $Word (@Candidates) {
next if grep($word,@SqlKeyWordList);
$FieldHash($Word)++;
}
评论:
my @Candidates=split(/[\s \( \) \+ \, \* \/ \- \n \ \= \r ]+/,$SqlSelectQuery );
答案 3 :(得分:0)
如何将每一行拆分为术语(用换行符替换每个括号,逗号和空格),然后排序:
perl -ne's/[(), ]/\n/g; print' < textfile | sort -u
你最终会得到很多内容,例如:
fieldname1 fieldname1 formatstring ltrim rtrim t_char