2011-09-09 11 views
-3

私はこの正規表現の質問

SELECT a, (SELECT b FROM w), (SELECT c FROM x) FROM y WHERE a IN (SELECT d FROM z) 

のようなクエリがあると私はPHPで

SELECT COUNT(*) FROM y WHERE a IN (SELECT d FROM z) 

に変換します。これはサンプルであり、quiresはこれとは異なります。

実際に正規表現は、最初のSELECTとFROMのペアの間のすべてをCOUNT(*)で置き換えるだけで、その後はSELECTに触れないようにする必要があります。また、最初のペアの中にいくつかの他のSELECT FROMペアがあり、それを置き換えることも考慮する必要があります。

私は

preg_replace('/SELECT (.*?) FROM/', 'SELECT COUNT(*) AS count FROM', $sql, 1) 

今これを使用するが、それは

+3

これは非常に奇妙な作業のようです。なぜそれをしようとしているのか、より高いレベルの問題に対するより良い解決策があるのか​​考えてみてください。 –

+1

実際のパターンは何ですか? 'str_replace( 'SELECT f1、f2、(SELECT f3 FROM t2)からt1 WHERE f1 IN(SELECT f4 FROM t)'、 'SELECT COUNT(*)from t1 where f1 IN FROM t) ') ' – NullUserException

+0

これはstr_replaceを使うことができる場合だけです – dynamic

答えて

1

preg_replaceから最初のSELECT *内のSELECTを検出しませんが、ここでやり過ぎのように思えます。 以上、str_ireplaceをお使いにならないのはなぜですか?

 

$sql = 'SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)'; 
$fixed_sql = str_ireplace('f1, f2, (SELECT f3 FROM t2)', 'COUNT(*)', $sql); 
 

クエリは常に同じではない場合

、次のことができます。

 

$sql = 'SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t)'; 
$fixed_sql = 'SELECT COUNT(*) ' . substr($sql, strpos($sql, ' FROM'); 
 

(未テストが、コンセプトは同じです)。

+0

クエリが常にこのようなものではありません:(サンプルです – Ali

+0

)次に、カラムリストをCOUNT(*)の右に置き換えたいのですか? –

1

方法について:

$sql = preg_replace("/^.*(FROM t1)/", "SELECT COUNT(*)$1", $sql); 
2

することは、あなたがCOUNT(*)SELECTFROMの間のすべてを置き換えるために正規表現を使用しましょう。

  1. 貪欲怠惰

SELECT間と FROMはのは、あなたの例の入力を見てみましょうすべてのものと一致し SELECTFROM
  • 間のすべてを一致:単純な正規表現パターンを使用して、2種類の方法でそれを行うことができます

    SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM t) 
    

    オプション1以下に一致します

    SELECT f1, f2, (SELECT f3 FROM t2) FROM t1 WHERE f1 IN (SELECT f4 FROM 
    

    (最初SELECTと最後FROM

    とオプション2次にマッチします:

    SELECT f1, f2, (SELECT f3 FROM 
    

    SELECT第一と第一FROM

    いずれかのパターンを置き換えると、SQLが破壊されます。もちろん、この特定のSQL入力を説明するためのパターンを作成する "巧妙な"方法がありますが、すべてのスマートな正規表現に対して、私(または他の誰か)がSQLスクリプトを "それによって壊れた。

    あなたは再帰的なパターンを使用すると思うかもしれないが、彼らは、書き込み、維持、彼らはあまりにも、このようなSQLコード破ることができるための痛みだ:

    SELECT ... WHERE x='FOO WHERE BAR' ... 
    

    (キーワードを含む文字列リテラルを)

    または

    SELECT ... WHERE ...  -- FOO WHERE BAR 
    

    (キーワードを含むコメント)

    私の答えは次のとおりです。正規表現を使用しないでください。代わりにSQL parserのようなものを使用してください。

    SELECT ... (...) FROM ...

    次作品:あなたが与えた特定のパターンについては

  • +0

    "reluctantly"を "lazily"に置き換えて編集しました。 –

    +0

    @Justin、いいえ、これのようにいいですよ、乾杯。 –

    +0

    あなたの答えをありがとう。私はそれを自分で考え出しました:{SELECT( ?:(?:(?! SELECT | FROM))++ | SELECT(?1)FROM)*)FROM} 6 – Ali

    1

    $sql = preg_replace('/^SELECT .*\(.*\) (FROM.*)$/', 'SELECT COUNT(*) $1', $sql); 
    

    しかし@Bartが指摘したように、このパターンからの偏差は、あなたのSQLを中断します。