2010-09-10 69 views
35

在我使用的舊服務器上,我無法使用準備好的語句,目前我正試圖在將其發送到MySQL之前完全轉義用戶輸入。 爲此,我使用PHP函數mysql_real_escape_string轉義MySQL通配符

由於這個函數不能逃脫MySQL通配符%和_我使用addcslashes來逃避這些。

當我送的東西,如:

test_test " ' 

到數據庫,然後讀出來的數據庫顯示:

test\_test " ' 

看着這個我不明白爲什麼_有前反斜槓,但是「和」不是 因爲它們全都用\確實被轉義了_'和「應該都是相同的,即所有的轉義字符都是可見的或者全部不可見。

是轉義\ S自動篩選出來

任何人都可以解釋一下嗎?

回答

79

_%在MySQL中通常不是通配符,不應該爲了將它們放入正常的字符串文字而轉義。 mysql_real_escape_string對此是正確和充分的。不應使用addcslashes

_%僅在LIKE匹配的情況下是特別的。如果要在LIKE語句中爲字面使用準備字符串,以便100%與百分之百匹配,而不僅僅是以百字符開頭的任何字符串,則您有兩級轉義操作需要擔心。

第一個是LIKE轉義。 LIKE處理完全在SQL內部進行,如果要將文字字符串轉換爲文字LIKE表達式,即使使用參數化查詢,也必須執行此步驟

在這個方案中,_%是特殊的,必須轉義。轉義字符也必須被轉義。根據ANSI SQL,除這些以外的字符必須不能被轉義:\'將是錯誤的。 (儘管MySQL通常會讓你擺脫困境。)

完成此操作後,您繼續進行第二級轉義,這是一種普通的舊字符串文字轉義。這發生在SQL之外,創建SQL,因此必須在LIKE轉義步驟之後完成。對於MySQL,如前所述,這是mysql_real_escape_string;對於其他數據庫會有不同的功能,您可以使用參數化查詢來避免必須這樣做。

這裏導致混淆的問題是在MySQL中使用反斜槓作爲轉義字符來嵌套轉義步驟!所以,如果你想匹配一個字符串與字面百分號,你必須雙反斜槓轉義,並說LIKE 'something\\%'。或者,如果這是一個PHP "文字,它也使用反斜槓轉義,"LIKE 'something\\\\%'"。哎呀!

根據ANSI SQL,這是不正確的,它說:在字符串文字反斜槓意思是文字反斜槓和轉義單引號的方式是'';在LIKE表達式中默認情況下根本沒有轉義字符。

因此,如果您想以便攜方式使用LIKE轉義,則應使用LIKE ... ESCAPE ...構造來覆蓋默認(錯誤)行爲並指定您自己的轉義字符。爲了理智,我們會選擇除了該死的反斜槓之外的東西!

function like($s, $e) { 
    return str_replace(array($e, '_', '%'), array($e.$e, $e.'_', $e.'%'), $s); 
} 

$escapedname= mysql_real_escape_string(like($name, '=')); 
$query= "... WHERE name LIKE '%$escapedname%' ESCAPE '=' AND ..."; 

或參數(例如,在PDO):

$q= $db->prepare("... WHERE name LIKE ? ESCAPE '=' AND ..."); 
$q->bindValue(1, '%'.like($name, '=').'%', PDO::PARAM_STR); 

(如果您想了解更多的便攜性派對的時候,你也可以有樂趣試圖解釋MS SQL Server和Sybase,其中[字符也是錯誤的,在LIKE聲明中是特殊的,並且必須被轉義。)

+4

我會再次爲「該死的反斜槓!」+1。 – BoltClock 2010-09-10 10:30:35

+0

謝謝,現在只是吸收這個...這真的幫助我擴展我的基本知識。愚蠢的是,儘管我並沒有使用任何LIKE語句,並且由於我認爲(請確認)%和_在LIKE語句中是瘋狂的,我實際上正在逃避%和_,實際上我正在浪費我的時間。但是,這讓我想到你爲什麼要在LIKE語句的上下文中轉義%或_。當然,使用LIKE語句的唯一原因是你可以使用它的通配符。 (請原諒我在這方面的有限知識) – Columbo 2010-09-10 11:06:05

+2

當然,但希望能夠搜索文字'%'或'_'字符是非常自然的。如果用戶在前端搜索'50%',那麼他們可能意味着他們正在尋找一個包含'50%'的字符串,而不是任何含有'50'的字符串。 – bobince 2010-09-10 11:08:29