某DBA在查看自己的數庫日志的時候,看到了數據庫服務器上出現了很多很怪異的SQL的Where條件語句,是下面這個樣子:(所有的where語句前都有了一個叫“1=1”的子條件)呵呵。
要理解這個事情的原因其實並不難。只要你是一個編寫數據庫的程序員,你就會知道——動態生成where後的條件的“麻煩”,那就是條件的“分隔”-and或or。下面聽我慢慢說來。
我們知道,大多數的查詢表單都需要用戶輸出一堆查詢條件,然後我們的程序在後台要把這些子條件用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;