最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解隱秘的?MySQL?類型轉換問題詳解

 更新時間:2022年10月14日 09:50:52   作者:架構精進之路  
這篇文章主要為大家介紹了詳解隱秘的?MySQL?類型轉換問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

1、問題開篇

本文來自于我近期工作中遇到的一個真實問題,稍作整理后分享給大家~

一張用戶表,其中 phone 添加了普通索引:

CREATE TABLE users (
	id bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
	name varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名稱',
	phone varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '手機',
	created_at timestamp NOT NULL DEFAULT '1970-01-01 16:00:00' COMMENT '創(chuàng)建時間',
	updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
	PRIMARY KEY (id),
	KEY idx_phone (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用戶表';

分別執(zhí)行以下 SQL:

1、字符串類型查詢

EXPLAIN SELECT * FROM users WHERE phone = '2';

執(zhí)行計劃如下:

2、數值型查詢

EXPLAIN SELECT * FROM users WHERE phone = 2;

執(zhí)行計劃如下:

發(fā)現問題:

當索引字段 `phone` 為字符串類型時,字符串查詢時候使用了索引`idx_phone`,而數值類型查詢時候竟無法使用索引`idx_phone`。

2、問題引申

假如索引字段為整型的話,那用字符串查詢時會不會走索引呢?

實踐出真知,我們來驗證一下。

同樣如上表,修改字段 `phone` 類型由 varchar 變更為 bigint:

ALTER TABLE users MODIFY COLUMN phone bigint(16) NOT NULL COMMENT '手機';

然后,分別執(zhí)行以下 SQL:

1、字符串類型查詢

EXPLAIN SELECT * FROM users WHERE phone = '2';

執(zhí)行計劃如下:

2、數值型查詢

EXPLAIN SELECT * FROM users WHERE phone = 2;

執(zhí)行計劃如下:

執(zhí)行后發(fā)現,無論是以字符串查詢還是以數值型查詢都會用到索引。

小結:

  • 當索引字段是數值類型時,數值型或者字符型查詢都不影響索引的使用。
  • 當索引字段是字符類型時,數值型查詢無法使用索引,字符型查詢可正常使用索引。

3、跟進探究

為什么會是這樣呢?其根源就是 MySQL 的隱式類型轉換。

3.1 什么是隱式類型轉換?

在 MySQL 中,當操作符與不同類型的操作數一起使用時,會發(fā)生類型轉換以使操作數兼容,則會發(fā)生隱式類型轉換。

即 MySQL 會根據需要自動將數字轉換為字符串,或者將字符串轉換為數字。

mysql> SELECT 1+'1';
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'

很明顯,上面的 SQL 語句的執(zhí)行過程中就出現了隱式轉化。

從結果我們可以判定,SQL1 中將字符串的“1”轉換為數字 1,而在 SQL2 中,將數字 2 轉換為字符串“2”。

3.2 如何避免隱式類型轉換?

3.2.1 清楚轉換規(guī)則

只有當清楚的知道隱式類型轉換的規(guī)則,才能從根本上避免產生隱式類型轉換。

參考 MySQL 文檔相關描述,確定隱式類型轉換規(guī)則:

1、兩個參數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 做比較時會返回 1,這兩種情況都不需要做類型轉換

2、兩個參數都是字符串,會按照字符串來比較,不做類型轉換

3、兩個參數都是整數,按照整數來比較,不做類型轉換

4、十六進制的值和非數字做比較時,會被當做二進制串

5、有一個參數是 TIMESTAMP 或 DATETIME,并且另外一個參數是常量,常量會被轉換為 timestamp

6、有一個參數是 decimal 類型,如果另外一個參數是 decimal 或者整數,會將整數轉換為 decimal 后進行比較,如果另外一個參數是浮點數,則會把 decimal 轉換為浮點數進行比較

7、所有其他情況下,兩個參數都會被轉換為浮點數再進行比較

驗證示例:

mysql> SELECT 'aa' + 1;
-> '1'
mysql> show warnings;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'aa' |
+---------+------+----------------------------------------+

上述示例中,將字符串 'aa' 和 1 進行求和,因為 'aa' 和數字 1 的類型不同,通過上述轉換規(guī)則并且經查看 warnings 可以確認:隱式類型轉化將字符串轉為了 double 類型。

由于字符串是非數字型的,所以就會被轉換為 0,因此計算結果:0+1=1

3.2.2 使用內置函數顯示轉換

MySQL 對數據進行類型轉換,提供了 cast() 和 convert()。

相同點:兩者都是進行數據類型轉換,實現的功能基本等同

不同點:兩者的語法不同:cast(value as type) 、 convert(value,type)

將數值型轉換為字符串型,應用示例如下:

mysql> SELECT CAST(123 as char);
-> '123'
mysql> SELECT CONVERT(123, char);
-> '123'

假如應用在開篇描述問題的查詢中,則如下所示:

EXPLAIN SELECT * FROM users WHERE phone = CAST(123 AS CHAR);

結果所示:

結果顯示同應用字符串類型參數一樣,可使用索引`idx_phone`。

3.2.3 類型保持一致

最簡單的一種,保證查詢應用規(guī)范,SQL 參數類型與數據庫中字段類型保持一致即可。

3.3 字符類型轉換

另外,關于字符串類型轉換的一些補充:

mysql> select '1a2b3c' = 1;
-> 1
mysql> select 'a1b2c3' = 0;
-> 1

從上面的例子可以得出:

  • 如果字符串的第一個字符就是非數字的字符,那么轉換為數字就是 0;
  • 如果字符串以數字開頭,那轉換的數字就是開頭的那些數字對應的值,直到遇到非數字字符才結束。

4、總結

本文主要從問題入手,繼而進行問題引申,最終挖掘出問題根源:MySQL 隱式類型轉換。

同時也告誡我們日常在寫 SQL 時一定要檢查參數類型與數據庫字段類型是否一致,否則可能造成隱式類型轉換,不能正常應用索引,造成慢查詢,甚至拖垮整個數據庫服務集群。

如果參數不一致,也可以考慮使用 CAST 函數顯性轉換成一致類型。

數據表設計及應用絕非易事,需要考慮的因素太多了,大家應用過程注意保持敬畏心。

以上就是詳解隱秘的 MySQL 類型轉換問題詳解的詳細內容,更多關于MySQL 類型轉換的資料請關注腳本之家其它相關文章!

相關文章

  • Mysql中的索引精講

    Mysql中的索引精講

    這篇文章主要給大家介紹了關于Mysql中索引的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Mysql具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-05-05
  • windows mysql 自動備份的幾種方法匯總

    windows mysql 自動備份的幾種方法匯總

    本篇文章主要對windows mysql 自動備份的幾種方法進行整理,具有很好的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • 解決mysql的賦權操作之GRANT ALL PRIVILEGES ON *.* TO ‘root‘@‘%‘ IDENTIFIED BY ‘123456‘ WITH GRANT OPTION問題

    解決mysql的賦權操作之GRANT ALL PRIVILEGES ON *.*

    這篇文章主要介紹了解決mysql的賦權操作之GRANT ALL PRIVILEGES ON *.* TO ‘root‘@‘%‘ IDENTIFIED BY ‘123456‘ WITH GRANT OPTION問題,本文給大家分享兩種情況分析分享解決方案,感興趣的朋友一起看看吧
    2022-11-11
  • mysql中操作表常用的sql總結

    mysql中操作表常用的sql總結

    這篇文章主要給大家介紹了mysql中操作表常用的sql的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • MySQL中count(*)執(zhí)行慢的解決方案

    MySQL中count(*)執(zhí)行慢的解決方案

    這篇文章主要介紹了MySQL中count(*)執(zhí)行慢的解決方案,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-06-06
  • mysql經典4張表問題詳細講解

    mysql經典4張表問題詳細講解

    MySQL是一種關系型數據庫管理系統(tǒng),可以通過連接不同的表將數據進行關聯查詢,下面這篇文章主要給大家介紹了關于mysql經典4張表問題的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-03-03
  • MySQL性能優(yōu)化的一些技巧幫助你的數據庫

    MySQL性能優(yōu)化的一些技巧幫助你的數據庫

    你完成了你的品牌新的應用程序,一切工作就像一個魅力;突然間,一個大爆發(fā)的用戶你的MySQL服務器,您的網站已關閉,是什么問題導致的呢?以下是MySQL性能優(yōu)化的一些技巧,將幫助你,幫助你的數據庫
    2013-01-01
  • Mysql排序和分頁(order by&limit)及存在的坑

    Mysql排序和分頁(order by&limit)及存在的坑

    這篇文章主要介紹了Mysql排序和分頁(order by&limit)及存在的坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • mysql 索引分類以及用途分析

    mysql 索引分類以及用途分析

    MySQL索引分為普通索引、唯一性索引、全文索引、單列索引、多列索引等等。這里將為大家介紹著幾種索引各自的用途。
    2011-08-08
  • 詳解mysql查詢緩存簡單使用

    詳解mysql查詢緩存簡單使用

    這篇文章主要介紹了詳解mysql查詢緩存簡單使用的相關資料,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-03-03

最新評論

景宁| 静海县| 深圳市| 绥德县| 扎鲁特旗| 嵊泗县| 太保市| 太保市| 舒城县| 衡阳市| 黑龙江省| 博罗县| 马鞍山市| 河北省| 正定县| 建湖县| 平湖市| 环江| 乌拉特前旗| 苗栗市| 嫩江县| 柘荣县| 区。| 沅陵县| 循化| 南投市| 宜兰市| 米易县| 什邡市| 岐山县| 湾仔区| 左贡县| 西吉县| 钦州市| 绩溪县| 达孜县| 尼玛县| 新河县| 西畴县| 黑龙江省| 岳池县|