首页 > 编程语言, 轶事趣闻 > SQL的Where语句

SQL的Where语句

2009年12月1日 发表评论 阅读评论 6,389 人阅读    

某DBA在查看自己的数库日志的时候,看到了数据库服务器上出现了很多很怪异的SQL的Where条件语句,是下面这个样子:(所有的where语句前都有了一个叫“1=1”的子条件)呵呵。

SQL Where Clause

要理解这个事情的原因其实并不难。只要你是一个编写数据库的程序员,你就会知道——动态生成where后的条件的“麻烦”,那就是条件的“分隔”-and或or。下面听我慢慢说来。

我们知道,大多数的查询表单都需要用户输出一堆查询条件,然后我们的程序在后台要把这些子条件用and组合起来。于是,把and加在各个条件的中间就成为了一件“难事”,因为你的程序需要判断:

  • 如果没有条件的话,则不需要where
  • 如果只有一个条件的话,不需要and.
  • 如果有多个条件的话,
    • 如果and是持续加在每个条件后面的话,那么就要判断是否是最后一个条件,因为最后一个不能加and.
    • 同样,如果and是要加在每个条件前面的话,你就需要判断是否是第一个,如果是,那就不加。

真是TMD太烦了,所以,编程“大拿”引入了“1=1”条件语句。于是,编程的难度大幅度下降,你可以用单一的方式来处理这若干的查询子条件了。而1=1应该会被数据库引擎优化时给去掉了。

<pre><code>$query = "SELECT name FROM table WHERE 1=1 ";

foreach($clauses as $key => $value){
    $query .= " AND ".escape($key)."=".escape($value)." ";
}
</code></pre>

呵呵,DBA怎么能够理解我们疯狂程序员的用心良苦啊

另外,在这里说一下,这样的做法看似很愚蠢,但很有效,在PHP的世界中,也有人使用下面这样的做法——使用了PHP的implode函数。

<pre><code>/**
 * @param string $base base of query, e.g. UPDATE table SET
 * @param string $logic logic for concatenating $assoc, e.g. AND
 * @param array $assoc associative array of `field`=>'value' pairs to concatenate and append to $base
 * @param string $suffix additional clauses, e.g. LIMIT 0,30
 * @return string
 */
function construct_sql($base, $logic, $clauses, $suffix='')
{
    // initialise array to avoid warnings/notices on some PHP installations
    $queries = array();

    // create array of strings to be glued together by logic
    foreach($clauses as $key => $value)
        $queries[] = "`" . escape($key) . "`='" . escape($value) . "'";

    // add a space in case $base doesn't have a space at the end and glue clauses together
    $query .= " " . implode(" $logic ",$queries) . " " . $suffix . ";";

    return $query;
}

/**
 * @param string $str string to escape for intended use
 * @return string
 */
function escape($str)
{
    return mysql_real_escape_string($str);
}
</code></pre>

于是,我们可以这样使用:(为什么我们要在update语句后加上“Limit 1”呢?这个关系到性能问题,关于这方面的话题,你可以查看本站的《MySQL性能优化的最佳20+条经验

<pre><code>$updates = array(
    'field1'=>'val1'
    'field2'=>'val2'
);
$wheres = array(
    'field1'=>'cond1',
    'field2'=>'cond2'
);
echo construct_sql(construct_sql("UPDATE table SET", ", ", $updates) . " WHERE ", " AND ", $wheres),"LIMIT 1");
</code></pre>
<pre></pre>

下面是输出结果:

UPDATE table SET `field1`='val1', `field2`='val2' WHERE `field1`='cond1' AND `field2`='cond2' LIMIT 1;

 

(全文完)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell.cn ,请勿用于任何商业用途)

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——
好烂啊有点差凑合看看还不错很精彩 (19 人打了分,平均分: 4.53 )
Loading ... Loading ...
  1. 2009年12月1日15:00 | #1

    哈哈,这可是个好东西,

    还有一种用法,以前看很多人ASP时,直接select * from article然后在程序里插入内容,
    我们可以换成select * from article where 1=2

  2. 2009年12月2日13:39 | #2

    但是这样的话,会造成索引没法利用。因为索引没法跨and,需要复合索引才可以跨and,如果第一个条件是1=1就啥索引都没法用了,具体还要看explain的分析。

  3. 2009年12月2日22:02 | #3

    @i_amok
    理论上说,根据mysql的官方文档,常数比较会被直接优化为true或false,索引的选取应该与此无关……

  4. 2009年12月3日11:53 | #4

    @upsuper

    恩,测试过了,你是正确的。

  5. sunseesiu
    2009年12月3日15:07 | #5

    呵呵,一直这么用的。

  6. gugaotianshi
    2009年12月7日10:06 | #6

    python 中有一个连接 list 的 join 函数,作用于类似 and 多个条件的情形,很好用,HOHO~~

  7. 阿段
    2009年12月15日22:37 | #7

    为什么不 where true and XXX ?

  8. 2009年12月16日20:15 | #8

    我用过一种字符串查找的方法,跟这个神似:

    存储tag的时候经常遇到用空格分割的一长串,比如“abcd bcd bcde”

    现在要找单词”bcd”,很难办,因为要区分是不是单独的单词,abcd和bcde是不算的

    于是先在前后加上空格,然后在搜索词前后加上空格,就变成了在” abcd bcd bcde ” 里面查找 ” bcd “,一个find函数就搞定了

  9. 2009年12月16日20:17 | #9

    (没写完,续上)

    后来干脆存储的时候就加上空格,比如:” abcd bcd bcde “,这样找起来就方便了,但是看起来有点怪异,跟楼主文中描述的很相近

  10. xLight
    2009年12月28日10:23 | #10

    根本没必要 1=1 ,就 where 1 后面跟AND就行了,
    看来这些程序员还是不够懒

  11. vvtommy
    2010年1月27日15:09 | #11

    @xLight
    我承认我很懒……

  12. mark3536
    2011年1月8日23:05 | #12

    i_amok :
    但是这样的话,会造成索引没法利用。因为索引没法跨and,需要复合索引才可以跨and,如果第一个条件是1=1就啥索引都没法用了,具体还要看explain的分析。

    i_amok@ccf?
    pgsql 规划器会自动判断and条件是否需要走索引然后分解成多个单条搜索最后UNION起来。

  13. mark3536
    2011年1月8日23:06 | #13

    xLight :
    根本没必要 1=1 ,就 where 1 后面跟AND就行了,
    看来这些程序员还是不够懒

    WHERE TRUE 更通用,而 WHERE 1 在MYSQL上正常,在pgsql上出错。

  14. bzhu
    2011年1月26日14:35 | #14

    @mark3536
    在Oracle上 where true 和 where 1 都非法。

  15. ayanmw
    2011年12月7日18:18 | #15

    where 1=1
    and condition
    那 本文的核心思想 是 支持 这样写法了…easy for 程序员,easy for 可读性.

  16. 2012年7月28日11:48 | #16

    这是一个好技巧

  1. 2011年9月2日15:52 | #1
  2. 2012年5月15日10:22 | #2
  3. 2012年5月16日14:04 | #3
  4. 2012年5月19日01:27 | #4