将自定义查询转换为SQL

时间:2011-02-07 10:14:14

标签: php sql mysql

使用PHP将以下输入转换为SQL的最佳方法是什么?

+a - includes a
+(c\d) - includes c or d but not both
+(c/d/e) - includes any of these
-f - does not include f

我有各种使用preg_replace或explode来循环执行并执行if语句,但没有任何工作可以持续工作。

我基本上需要转变类似

+a +(c/d/e)

SELECT * FROM the_table 
WHERE description LIKE "%a%" 
AND (description LIKE "%c%" OR description like "%d%" OR description LIKE "%$e%")

谢谢!

更新:

这是我的尝试。我确信有一种更简单的方法......

public function custom_query($query){

    $fields = " feed_items.description ";

    $return_query = "";

    $query = str_replace("'", '', $query);

    $pluses = explode('+',$query);

    foreach($pluses as $plus){

            $plus = trim($plus);

            if (substr($plus,0,1) == '('){
                $return_query .= 'AND (';

                $plus = str_replace(array('(',')'), '', $plus);

                $ors = explode('/', $plus);

                foreach($ors as $or){
                    if ($or){
                        $return_query .= $fields." LIKE '%".$or."%' OR";
                    }
                }

                $return_query = rtrim($return_query, ' OR');
                $return_query .= ' )';
            } else {
                if ($plus){
                    $return_query .= ' AND ' . $fields.' LIKE '.'"%'.$plus.'%"';
                }
            }

        }

    $negatives = explode('-',$query);

    foreach($negatives as $negative){

            $negative = trim($negative);

            if (substr($negative,0,1) == '('){
                $return_query .= 'AND (';

                $negative = str_replace(array('(',')'), '', $negative);

                $ors = explode('\\', $negative);

                foreach($ors as $or){
                    if ($or){
                        $return_query .= $fields." NOT LIKE '%".$or."%' OR";
                    }
                }

                $return_query = rtrim($return_query, ' OR');
                $return_query .= ' )';
            } else {
                if ($negative){
                    $return_query .= ' AND ' . $fields.' NOT LIKE '.'"%'.$negative.'%"';
                }
            }

        }

    $return_query = ' AND '.ltrim($return_query, ' AND ');

    return $return_query;

}

2 个答案:

答案 0 :(得分:1)

因为您不需要嵌套表达式。这很简单,正则表达式实际上只是懒惰:

$sql = preg_replace_callback("'
           ([+-])            # AND or NOT
           (\w+              # capture a single word
           | \(              # or something enclosed in literal braces
                (\w+         # word
                  ([/\\\\])?    # logical delimiter
                [^)]*)       # remainder words and/or delimiters
             \)
           )'x",
       "to_sql", $search_pattern);

function to_sql($match) {
    @list($uu, $logical, $word, $words, $or) = $match;

    if ($logical == "+") {
        $sql = " AND (";
    }
    else {
        $sql = " OR (";
    }

    if ($words) {
        $words = explode($or, $words);
    }
    else {
        $words = array($word);
        $or = "/";
    }

    foreach ($words as $i=>$word) {
        $words[$i] = "description LIKE '%$word%'";
    }

    $or = ($or == "/") ? " OR " : " XOR ";
    $sql .= implode($or, $words);

    return "$sql)";
}

它将返回以“AND”开头的语句,可以对其进行调整,但更容易作弊,只需将“TRUE”前置为有效的WHERE子句。

答案 1 :(得分:1)

$pattern = "+a +(c/d/e)";

// replace a, c, d, e with "description like "%something%"
$pattern = preg_replace('#[^()+\\-\\\\/\s]#', 'description like "%$0%"', $pattern);

// replace operators
$replacements = array(
    '+'  => ' and ',
    '-'  => ' and not ',
    '\\' => ' xor ',
    '/'  => ' or ',
);
$pattern = str_replace(array_keys($replacements), $replacements, $pattern);
$pattern = trim($pattern);

// remove first "and"
// * "and something and something_else" becomes "something and something_else"
// * "and not something and something_else" becomes "not something and something else"
$pattern = preg_replace('#^and #', '', $pattern);

Patten应该从+-或没有任何运算符开始。

不确定将\替换为xor - 取决于您希望如何处理(a\b\c)(a\b\c\d)等。