MySQL 一些讓人容易忽視的知識點

2022-03-28 21:38:55 字數 3143 閱讀 3015

一下都是mysql在實際開發中,經常容易讓人忽視的點,希望對您有幫助,幫您越過這些坑。

一:mysql and優先順序大於or

今天上班時在寫乙個業務的時候又發現了乙個mysql的問題:

我們的業務是這樣的,使用者可以修改自己的行資料,但這些行資料中有些資料是不能重複的,舉個例子比如我們如果要開公司就要去工商局註冊公司名,這時工商局可能就有乙個《公司名》的表,這個表有乙個主鍵id欄位,然後有乙個公司名稱字段,公司英文名稱字段,以及公司地點字段等等其他的資料字段,很明顯這裡的公司名以及公司英文名必須是唯一,因為不能有同名的公司。然後我們的業務提供給這個公司乙個修改自己這條行資料的功能,比如你可以修改自己公司的中文名稱或英文名稱,或者位址等等,但是因為公司名是唯一的,所以在我們update資料前,我們先做了乙個判斷,看是否使用者提交的資料中的公司名稱以及英文是否已經存在,如果已經存在則告訴他,中文公司名或者是英文名已存在,請修改後重新提交。這裡看似業務沒有問題,但其實我們稍加測試後就發現了問題:

當使用者在修改資料時只修改了中文名稱或者英文名稱時,此時就會有問題,比如使用者想更改自己的英文公司名,因為使用者提交的資料的中文名稱還是原來的,所以我們在查詢時發現這個中文名已經存在,所以會返回修改失敗。

比如我們的判斷語句是:select * from base_pop where name=$name or en-name=$en-name;只要這個查詢返回結果集,就說明修改後的公司名已存在,修改失敗。但是我們這裡並沒有考慮到區域性修改的問題,甚至是如果你只想修改公司位址這種可以重複的資訊,而沒有更改時中英文名稱時,這條sql都會有返回集,所以都會返回修改不成功。

所以後來我們sql更改為:select * from base_pop where name=$name or en-name=$en-name and id!=$id;這樣修改後,基本上就沒有問題了。已經可以完成大部分的業務需求,然而這裡卻引出了mysql另外的乙個問題,也就是我們今天的主題!

請看下圖:

從上面這兩張圖中我們可以看到,當我們寫:(a,b,c為三個表示式,如name=1這種),  

where a and/or b and/or c; 這種where條件是有時候他的返回集和 where (a and/or b) and/or c; 的返回集一樣,而有的時候又和where a and/or (b and/or c); 的返回集一樣。這是什麼情況呢,這裡和我們設想的應該和c語言一樣,自左向右運算的想法並不一樣。到底mysql自己的運算機制是自左向右還是自右向左的呢,怎麼有的時候是向左有的時候是向右呢?

然而我們仔細檢視後返現,會發現上面兩種圖有乙個共性,不管是自作向右還是自右向左,我們發現返回結果集相同的sql語句的括號總是括這包含and的語句,難道mysql預設是先執行and語句的?

於是我們檢視《mysql手冊》,得出以下結論:

我們發現,果然和我們的猜想一樣,and的操作符優先順序就是比or高,mysql是用c語言寫的,其實c語言在這裡也是一樣的,在c中&&的操作符優先順序就是比||高,所以mysql這裡也是一樣的,並不僅僅是簡單的左結合性的問題。

這個在開發中也是比較常見的,有的時候會使用不至兩個表示式。

二:mysql中文亂序

今天上班,發現了乙個有趣的東西,我們有一張表存的是國內運營商的資料,如id,name之類的。我們有乙個業務,需要讓使用者選擇自己對應的運營商,所以後台需要向前端返回運營商的名字以及id,name用來給使用者展示,id用來記錄使用者選擇了什麼。如下圖:

首先,標的結構如下:

表裡的資料如下:

根據業務,我們寫入了如下的sql語句:

沒想到返回的結果街竟然是這樣的,為什麼會是亂序的呢?為什麼id和name都沒有呈現出一定的順序?

仔細看了看,我發現返回的結果集只有兩個字段,這不僅讓我想起了innodb的非聚集索引的結構,(可參看《資料庫為什麼要用b+數結構--mysql索引結構的實現》),難道是因為這條sql使用了name欄位上的非聚集索引?所以主鍵相對無序,但是name欄位也沒有表現出順序啊,但是如果我們的查詢語句是這樣寫的,按理說應該就是使用的非聚集索引。此時我有想到哦了myisam的倒排索引的全文索引,的確,innodb的b+樹索引在處理中文的時候是會有一點問題。於是我們做出如下測試:

我們先在表中插入幾條測試資料,讓這幾條資料是英文的:

然後再執行之前的查詢語句,

果不其然,這裡我們新插入的a,b,c確實表現出的他應該有的順序。

所以這裡的中文應該是有序排列的,只不過沒有對應拼音,這應該和中文字元的編碼有關係,我們都知道gbk,utf-8等等,漢字在計算機中的儲存並不是用拼音,所以沒有展現出有序性,如果我們把這些漢字轉換成2進製,應該就能看到他們是有序排列的。所以我們在開發中如果要有序,需要自己加上order by:

最後,我們再做乙個測試,看看我們的猜想對不對,是否使用的非聚集索引:如下

首先,表中的索引有:

我們的sql使用的索引是:

果不其然,使用的就是name欄位的索引。

這個在實際開發中還是挺常見的,在innodb中當我們使用中文的時候,還是要多加注意。

容易忽視的一些安全錯誤

無論網路的規模怎樣,每個網路都面臨著安全問題。比如 保護私有資料不被非法訪問,網路能夠阻擋外來的攻擊行為等等。防病毒軟體 防火牆 ids等措施現在已經不新鮮了,任何企業都明白使用它們保護自己的網路的必要性。甚至的個人pc,病毒和防火牆也已經得到了普及。可是,攻擊仍然每天發生且以攻擊成功的結果在發生。...

Android開發中容易被忽視的一些注意事項

一 謹慎選擇包名 包名 package name 就相當於一款應用在戶口本上登記的名字,是系統用來區分不同應用的字段。重複的包名會被認為是同一款應用,不能同時安裝在乙個系統裡。一般來說,包名建議使用網域名稱反序。比如豌豆莢的 網域名稱是 www.wandoujia.com,那麼豌豆莢的一系列 and...

php一些容易讓我忘記的用法

1 define l ceshi,測試 m ce ceshi m ceshi l m ce eval echo m ceshi echo constant m ceshi 2 m a 0 m b 1 m str m a m b f echo m str function f echo m str m...