查看数据库日志,发现Where前都有一个“1=1”

某DBA在查看自己的数据库日志的时候,看到了数据库服务器上出现了很多很怪异的SQL的Where条件语句,是下面这个样子:(所有的where语句前都有了一个叫“1=1”的子条件)呵呵。3 U0 {* n: u) I- y# E1 G* z6 ~2 V

sql.where.jpg

! r  i( W8 z# t+ @) |2 a

* I- |+ g” N1 N/ S” X% w
要理解这个事情的原因其实并不难。只要你是一个编写数据库的程序员,你就会知道——动态生成where后的条件的“麻烦”,那就是条件的“分隔”-and或or。下面听我慢慢说来。
, i7 A’ e* p” q$ c/ T( u6 X; A9 p9 d( c. `6 m- U

& k# u0 I$ c8 t$ k- ]我们知道,大多数的查询表单都需要用户输出一堆查询条件,然后我们的程序在后台要把这些子条件用and组合起来。于是,把and加在各个条件的中间就成为了一件“难事”,因为你的程序需要判断:0 a& F9 w, D9 A. P

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

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

  1. <pre><code>$query = “SELECT name FROM table WHERE 1=1 “;  
  2. foreach($clauses as $key => $value){  
  3. $query .= ” AND “.escape($key).”=”.escape($value).” “;  
  4. }  
  5. </code></pre>

复制代码

呵呵,DBA怎么能够理解我们疯狂程序员的用心良苦啊
0 l6 n1 \) R! L+ b& {‘ W另外,在这里说一下,这样的做法看似很愚蠢,但很有效,在PHP的世界中,也有人使用下面这样的做法——使用了PHP的implode函数。

  1. <pre><code>/**
  2. * @param string $base base of query, e.g. UPDATE table SET
  3. * @param string $logic logic for concatenating $assoc, e.g. AND
  4. * @param array $assoc associative array of `field`=>’value’ pairs to concatenate and append to $base
  5. * @param string $suffix additional clauses, e.g. LIMIT 0,30
  6. * @return string
  7. */
  8. function construct_sql($base, $logic, $clauses, $suffix=”)
  9. {
  10.     // initialise array to avoid warnings/notices on some PHP installations
  11.     $queries = array();
  12.     // create array of strings to be glued together by logic
  13.     foreach($clauses as $key => $value)
  14.         $queries[] = “`” . escape($key) . “`='” . escape($value) . “‘”;
  15.     // add a space in case $base doesn’t have a space at the end and glue clauses together
  16.     $query .= ” ” . implode(” $logic “,$queries) . ” ” . $suffix . “;”;
  17.     return $query;
  18. }
  19. /**
  20. * @param string $str string to escape for intended use
  21. * @return string
  22. */
  23. function escape($str)
  24. {
  25.     return mysql_real_escape_string($str);
  26. }
  27. </code></pre>

复制代码

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

  1. <pre><code>$updates = array(
  2.     ‘field1’=>’val1’
  3.     ‘field2’=>’val2’
  4. );
  5. $wheres = array(
  6.     ‘field1’=>’cond1’,
  7.     ‘field2’=>’cond2’
  8. );
  9. echo construct_sql(construct_sql(“UPDATE table SET”, “, “, $updates) . ” WHERE “, ” AND “, $wheres),”LIMIT 1”);
  10. </code></pre>
  11. <pre></pre>

复制代码

下面是输出结果:

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

复制代码

(全文完)3 c! T9 ]& A’ s4 w



本文固定链接: http://www.ntxz.net/?p=595 | 周忞 | 吉心的记事本



该日志由 吉心 于2010年01月10日发表在 懒得分类, 旧版博客 分类下, 你可以发表评论
在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: 查看数据库日志,发现Where前都有一个“1=1” | 周忞 | 吉心的记事本

查看数据库日志,发现Where前都有一个“1=1”:等您坐沙发呢!

发表评论

您必须 [ 登录 ] 才能发表留言!