Mysql的隱式轉換

Mysql的隱式轉換:

來我們先看看官方文檔:
        When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly. 
        For example, MySQL automatically converts strings to numbers as necessary, and vice versa.

我們常見的different types operands 有:

1.strings and numbers        

當值類型和字符串類型進行比較的時候,Mysql做的操作是,把字符串類型轉換成值類型

我們實際測試一下看看:

mysql> select '2.34'=2.34,'2.34abc'=2.34,'abc2.34'=2.34,'2 .34abc'=2.34,'2 .34abc'=2;
+-------------+----------------+----------------+-----------------+--------------+
| '2.34'=2.34 | '2.34abc'=2.34 | 'abc2.34'=2.34 | '2 .34abc'=2.34 | '2 .34abc'=2 |
+-------------+----------------+----------------+-----------------+--------------+
|           1 |              1 |              0 |               0 |            1 |
+-------------+----------------+----------------+-----------------+--------------+
1 row in set, 4 warnings (0.00 sec)

mysql> show warnings;
+---------+------+----------------------------------------------+
| Level   | Code | Message                                      |
+---------+------+----------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '2.34abc'  |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'abc2.34'  |
| Warning | 1292 | Truncated incorrect DOUBLE value: '2 .34abc' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '2 .34abc' |
+---------+------+----------------------------------------------+
4 rows in set (0.00 sec)

mysql> select '2.34'+1,'2.34abc'+1,'abc2.34'+1;
+----------+-------------+-------------+
| '2.34'+1 | '2.34abc'+1 | 'abc2.34'+1 |
+----------+-------------+-------------+
|     3.34 |        3.34 |           1 |
+----------+-------------+-------------+
1 row in set, 2 warnings (0.02 sec)

        所以在寫sql的時候,我們儘量要避免類型間的隱式轉換,如果隱式轉換的是入參的話,查詢結果可能不準;如果隱式轉換的是字段的話,那麼這樣轉換之後,即使在該列上有索引,也無法使用索引的快速掃描了。
        舉例說明:

mysql> show create table test1017\G
*************************** 1. row ***************************
       Table: test1017
Create Table: CREATE TABLE `test1017` (
  `id` int(10) NOT NULL,
  `m1` varchar(5) DEFAULT NULL,
  `m2` int(4) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_1017_m1` (`m1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> insert into test1017 values(1,'12',1),(2,'12a',2),(3,'a12',3),(4,'12.a',4);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> explain select id,m1 from test1017 where  m1=12;
+----+-------------+----------+------------+-------+---------------+-------------+---------+------+------+----------+--------------------------+
| id | select_type | table    | partitions | type  | possible_keys | key         | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+----------+------------+-------+---------------+-------------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | test1017 | NULL       | index | idx_1017_m1   | idx_1017_m1 | 18      | NULL |    4 |    25.00 | Using where; Using index |
+----+-------------+----------+------------+-------+---------------+-------------+---------+------+------+----------+--------------------------+
1 row in set, 3 warnings (0.00 sec)

mysql> explain select id,m1 from test1017 where  m1='12';
+----+-------------+----------+------------+------+---------------+-------------+---------+-------+------+----------+-------------+
| id | select_type | table    | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra       |
+----+-------------+----------+------------+------+---------------+-------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | test1017 | NULL       | ref  | idx_1017_m1   | idx_1017_m1 | 18      | const |    1 |   100.00 | Using index |
+----+-------------+----------+------------+------+---------------+-------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> select id,m1 from test1017 where  m1=12;
+----+------+
| id | m1   |
+----+------+
|  1 | 12   |
|  4 | 12.a |
|  2 | 12a  |
+----+------+
3 rows in set, 3 warnings (0.00 sec)

mysql> select id,m1 from test1017 where  m1='12';
+----+------+
| id | m1   |
+----+------+
|  1 | 12   |
+----+------+
1 row in set (0.00 sec)

        我們可以看到在入參是值類型,導致m1需要做隱式轉換之後,我們發現sql語句不走idx_1017_m1的快速掃描了,轉而走了索引全掃描。
        而且我們發現,入參是12和‘12’時,查詢結果集不一樣!!

總結:
        1.當值類型和字符串類型進行運算的時候,Mysql把字符串類型轉換成值類型
        2.如果字符串不是以值類型開頭的,那麼Mysql在比較時直接將字符串類型轉化成數值0
        3.如果字符串是以值類型開頭的,那麼Mysql在運算時會從字符串的首位開始,"儘可能的截取值",然後返回

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章