2017-10-09 146 views
2

我有以下方法:(笨模型)MySQL查詢的WHERE區分大小寫

/** 
* Get an Ad based on its hash 
* 
* @param $hash 
* @return bool 
*/ 
public function getAdbyHash($hash) 
{ 
    $this->db->select('category.id as category_id, category.subcat as category_name, provinces.id as provinces_id, provinces.prov_name, users.id as users_id, users.*, ads.*'); 
    $this->db->where('ads.hash', $hash); 

    $this->db->join('category', 'category.id = ads.subcat_id'); 
    $this->db->join('provinces', 'provinces.id = ads.province_id'); 
    $this->db->join('users', 'users.id = ads.user_id', 'left'); 

    $r = $this->db->get('ads'); 

    //echo $this->db->last_query(); 

    if ($r->num_rows() == 1) { 
     $ad = $r->result()[0]; 
     return $ad; 
    } 
    return FALSE; 
} 

而且它的正常工作。但是今天我試圖破解自己在URL中引入類似的散列,以及它的工作,但這不是期望的行爲。
所以這個散列:編輯/ zIpM41NkS8igFXaC必須NO是相同的編輯/ zIpM41NkS8igFXac

注意最後一個字符(C/C) 我怎樣區分大小寫的查詢?

我的方法是使用Codeigniter的特定方法,而不是使用直接的SQL語句。但無論如何工作。

+2

更改列的編碼來區分sensititve?也請看看[post](https://stackoverflow.com/questions/5629111/how-can-i-make-sql-case-sensitive-string-comparison-on-mysql) – Rulisp

+1

[mysql ,通過codeigniter區分大小寫比較](https://stackoverflow.com/questions/2538114/mysql-case-sensitive-compare-through-codeigniter) – Vixed

+0

我該怎麼做? –

回答

2

嘗試使用:

$this->db->where('ads.hash like binary "'.$hash.'"', NULL, FALSE) 

$這 - > DB->其中()接受一個可選的第三個參數。如果您將其設置爲FALSE,CodeIgniter將不會嘗試使用反引號來保護您的字段或表 名稱。 CodeIgniter Doc. Where

要清理數據,你可以嘗試這樣的:

public function getAdbyHash($hash) 
{ 
    $db = get_instance()->db->conn_id; 
    $hash= mysqli_real_escape_string($db, $hash); 
    $this->db->select('category.id as.....' 
    $this->db->where('ads.hash like binary "'.$hash.'"', NULL, FALSE); 
    $this->db->join('cate......' 
+0

好的,這個工程!但是,什麼意思是第二個和第三個參數? –

+1

字符串串聯是非常危險的建議。 –

+0

好了,現在明白了。哈希是從URL GET參數獲得的。而且我不保護字段名稱。那麼,這是MySQL注入還是XSS的風險? –

2

由於@Vixed建議,你可以修改你where條件。

但同時,你可以修改你ads.hash列區分大小寫

ALTER TABLE `ads` MODIFY `hash` VARCHAR(255) CHARACTER SET utf8 COLLATE `utf8_bin`; 

需要注意的是,對於Unicode,你只能使用utf8_bin用於區分大小寫的比較。這是因爲MySQL沒有區分大小寫的Unicode排序規則(請參見post

但是,如果您的排序規則爲latin,只需將其更改爲latin_general_cs即可。

另外,如果你在你列的一些具體數據,你可以看看這個SO後 - How to change Column Collation without losing or changing data?

UPD。性能說明

那麼,like binary看起來像一個非常昂貴的操作(如提到here)。另外,我覺得,你會希望看到這個帖子:SQL 'like' vs '=' performanceWhat effects does using a binary collation have?

無論如何,這需要測試

+0

嗯,很棒的提示。但是,百萬個問題:哪個解決方案更優化?我是MySQL的新手,但我知道每毫秒的數量。謝謝! –

+0

@ErichGarcía回答已更新。測試是非常必要的,因爲如果每個查詢都會丟失幾個ms,它在某個級別上並不重要。但是,如果差異將在幾十毫秒甚至更大,那麼您應該優化您的搜索。一旦我使用字符串的CRC32散列的額外列進行搜索優化 – Rulisp

+2

@ErichGarcía,則無需進行比較。這是正確的解決方案以及最優化的解決方案。幾乎總是避免在WHERE條款中強制轉換,強制轉換和轉換。如其他答案中所示使用字符串連接和插值是一種不可接受且危險的做法。 –