3

select 句の「from」キーワードの後に​​あるすべてのテーブル名をキャプチャするために、C# の正規表現を作成する必要があります。例えば

.
.
.
SELECT field1, field2
FROM table1
WHERE condition1
.
.
.
SELECT field3, field4
FROM table2
WHERE condition2
.
.
.

読み取ろうとしているファイルには複数の select 句があり、select と from の間には任意の文字 (改行、「:」、「_」、およびその他の文字を含む) を含めることができます。すべてのテーブル名を取得するには、正規表現をどのように作成すればよいですか?

ありがとう

編集: すべてのテーブル名を取得する方法を見つけました。

\s*SELECT[^;]*FROM\s*(?<key>[^\n]*)

これはいつか誰かを助けるかもしれません。ありがとう

4

3 に答える 3

3

すべてのクエリにテーブルが 1 つしかない場合や、コメントを使ったおかしなビジネスがない場合を除き、これに正規表現を使用することは命題を失います。その代わり:

SET SHOWPLAN_ALL ON;

--All your queries here

set showplan_allドキュメントを参照してください。

正規表現が複雑になるというのは、そういう意味です。これらは考慮事項の一部にすぎません。

  • 引用符で囲まれた文字列の開始を検出する必要があり"ます。終了文字が 2 重になっている場合は終了しません (つまり、 の後に停止しません)。'['this is ''fun'', he said'is

  • 引用符で囲まれていない単一行のコメントを除外--し、次の CRLF で終了する必要があります。コメント内の引用符は、通常どおり文字列を開始しません。

  • 引用符内または単一行のコメント内にない複数行のコメント ( で始まる/*) を除外し、ターミネータ以外のすべてをスキップする必要があります*/。正規表現では、必ず*バックスラッシュで文字をエスケープしてください\

  • 次に、適切な単語境界を持つ有効な句を見つける必要があります(たとえば、列名またはでFROM誤った一致はありません)。SelfRomAfroMonkey

  • FROM 句を適切に終了するWHEREには、、、、、および;GROUP BYを含むキーワードが表示されたらキャプチャを停止する必要があります。また、SQL クエリにはセミコロン ターミネータが必要ないため、、、、、、などで終了する必要があります。HAVINGORDER BYWITH;SELECTDBCCSETCREATEALTERDROP

  • しかし、前の 2 つのポイントでさえ、それだけでは十分ではありません。クエリが次のようになっている場合はどうでしょうか。

    SELECT *
    FROM
       MyTable T
       INNER JOIN (
          SELECT * FROM YourTable Y WHERE Active = 1
       ) X ON T.ID = Y.ID
       INNER JOIN AnotherTable A
          ON X.AID = A.AID
    

    ここで、括弧を解析する必要があり、これらのキーワードのいずれかが表示されたときに FROM 句のキャプチャを停止しないでください。そして、括弧の深さを追跡し、その数になるまで無視し続ける必要があります。そして最後に、これらをどうするかというと、派生テーブルはテーブルと同じようなものなので、派生テーブルの全文が必要なのか、それともその中のテーブルだけが必要なのか?

これをすべて行うには、テキスト内の最初の有効な場所から照合を開始するだけではいけませんFROM。これは、引用符またはコメント内にある可能性があるためです。最初からすべてのテキストを一致させる必要があります。それが、正規表現で一致すべきでない場所を見つけないようにする唯一の方法だからです。

これが私が思いついたもので、コメントを処理しようとするだけです。引用すらありません。そして、そこにあるものではなく、 from句を見つけるところまでしか行きません。さらに、実際の FROM 句のキャプチャ グループを調べるときに混乱が生じないように、括弧によるキャプチャを防止する必要があります。

(?:(?:-(?!-)|/(?!\*)|f(?!rom)|[^-f/])|--[^\n]*\n|/\*(?:\*/)*\*/)*from()

そして、おそらくエラーがはびこっていて、少し遊んだら全体を再考する必要があり、全体として、それは膨大な時間の無駄になります.

あなたは、そのようなことをうまく成し遂げるのがどれほど難しいかを過小評価していると思います。しかし、完全に信頼できる解決策があります。上で示したもの: SQL Server にすべてを解析させます。返されたプランは簡単に解析できるように構造化されているため、簡単に解析できます。

于 2012-12-20T10:01:05.993 に答える
1

まず、このチュートリアルをチェックしてください: http://www.codeproject.com/Articles/9099/The-30-Minute-Regex-Tutorial

次のような正規表現を確認してください。((?<=FROM )[^\s]+)

この正規表現は、(空白を含む) 直後に読み取りを開始"FROM "し、最初の空白で読み取りを停止します。(^\s)

このようなことを試してみると

foreach (Match m in Regex.Matches(input, @"((?<=FROM )[^\s]+)")
{
    string output = m.Value;
}

編集:

この正規表現について 100% 確信があるわけではありません。名前の末尾に改行文字がある場合は、おそらくこれでうまくいくでしょう。@"((?<=FROM)[^\n]+))ただし、出力文字列の先頭に空白がある可能性があるため、出力をトリミングする必要があります。

于 2012-12-20T09:41:19.970 に答える
0
var input = "select name from Table1 where id =2";
var pattern = @"from\s*(.*?)\s*where"; // where car= is the first delimiter and ; is the second one
var result = Regex.Match(input, pattern).Groups[1].Value;
MessageBox.Show(result);
于 2012-12-20T09:45:01.050 に答える