簡體   English   中英

如何使用Perl從SQL中提取字段名稱?

[英]How can I extract field names from SQL with Perl?

我在文本文件中有一系列選擇語句,我需要從每個選擇查詢中提取字段名稱。 如果某些字段不使用諸如to_char()等嵌套函數,這將很容易。

給定的select語句字段可能具有多個嵌套括號,例如:

ltrim(rtrim(to_char(base_field_name, format))) renamed_field_name,

還是僅以base_field_name作為字段的簡單情況,正則表達式在Perl中會是什么樣?

不要嘗試編寫正則表達式解析器(盡管perl正則表達式可以處理類似的嵌套模式),請使用SQL :: Statement :: Structure

為什么不問目標數據庫本身如何解釋查詢呢?

在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丑陋! 有點嘗試將始終為false的條件附加到SELECT上,以便當您execute()時,SQL引擎不必執行任何實際工作。 這是一種非常幼稚的方法- /\\bWHERE\\b/i測試無法正確地識別出SQL WHERE子句,而不是簡單的正則表達式可以正確地解析出SELECT字段名稱-但它可能會起作用。

在辦公室中一個有點相關的問題中,我使用了:

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)++;
} 

評論:

  1. SqlKeyWordList包含所有可能在SQL語句中使用的SQL關鍵字(我們使用MySQL,有很多SQL方言,選擇/構建此列表是可行的,請看下面的評論!)。 如果有人決定使用關鍵字作為字段名稱,那么您最終將需要一個正則表達式(更好地重構代碼)。
  2. 將SQL語句拆分為單詞列表,這是最棘手的部分,將需要tweeking。 現在,它使用Perl的“空間”概念(=不在單詞中)進行拆分。
    拆分字段列表(選擇a,b,c),SQL的“ from”部分在這里可能是適當的,具體取決於您的SQL語句。
  3. %MyFieldHash將在每個選擇字段中包含一個條目(包括亂碼,直到您在(2)中驗證了SqlKeyWorkList和正則表達式為止

謹防

  • 這段代碼中沒有什么是Python無法完成的。
  • 如果您可以影響所說的SQL語句的創建,您的生活就會輕松得多。 (例如,確保每個字段都寫有注釋)
  • 在這種解析方法中,有很多事情可能會/將要出錯,您真的應該通過更改過程來完全回避問題(從長遠來看節省時間)。
  • 這是我們在辦公室使用的正則表達式
my @Candidates=split(/[\s
                  \(
                  \)
                  \+
                  \,
                  \*
                 \/
                  \-
                  \n
                  \
                  \=
                  \r
                 ]+/,$SqlSelectQuery
               );

如何將每行分割成多個字詞(用換行符替換每個括號,逗號和空格),然后進行排序:

perl -ne's/[(), ]/\n/g; print' < textfile | sort -u

您最終將獲得很多內容,例如:

fieldname1
fieldname1
formatstring
ltrim
rtrim
t_char

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM