《Mysql學(xué)習(xí)MySQL的隱式類型轉(zhuǎn)換整理總結(jié)》要點(diǎn):
本文介紹了Mysql學(xué)習(xí)MySQL的隱式類型轉(zhuǎn)換整理總結(jié),希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
MYSQL實(shí)例前言
MYSQL實(shí)例前幾天在看到一篇文章:價(jià)值百萬的 MySQL 的隱式類型轉(zhuǎn)換感覺寫的很不錯(cuò),再加上自己之前也對(duì)MySQL的隱式轉(zhuǎn)化這邊并不是很清楚,所以就順勢(shì)整理了一下.希望對(duì)大家有所幫助.
MYSQL實(shí)例當(dāng)我們對(duì)不同類型的值進(jìn)行比較的時(shí)候,為了使得這些數(shù)值「可比較」(也可以稱為類型的兼容性),MySQL會(huì)做一些隱式轉(zhuǎn)化(Implicit type conversion).
MYSQL實(shí)例比如下面的例子:
MYSQL實(shí)例
mysql> SELECT 1+'1';
-> 2
mysql> SELECT CONCAT(2,' test');
-> '2 test'
MYSQL實(shí)例很明顯,上面的SQL語句的執(zhí)行過程中就出現(xiàn)了隱式轉(zhuǎn)化.并且從結(jié)果們可以判斷出,第一條SQL中,將字符串的“1”轉(zhuǎn)換為數(shù)字1,而在第二條的SQL中,將數(shù)字2轉(zhuǎn)換為字符串“2”.
MYSQL實(shí)例MySQL也提供了CAST()函數(shù).我們可以使用它明確的把數(shù)值轉(zhuǎn)換為字符串.當(dāng)使用CONCA()
函數(shù)的時(shí)候,也可能會(huì)出現(xiàn)隱式轉(zhuǎn)化,因?yàn)樗M膮?shù)為字符串形式,但是如果我們傳遞的不是字符串呢:
MYSQL實(shí)例
mysql> SELECT 38.8, CAST(38.8 AS CHAR);
-> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
-> 38.8, '38.8'
MYSQL實(shí)例隱式轉(zhuǎn)化規(guī)則
MYSQL實(shí)例官方文檔中關(guān)于隱式轉(zhuǎn)化的規(guī)則是如下描述的:
MYSQL實(shí)例If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
MYSQL實(shí)例翻譯為中文就是:
MYSQL實(shí)例注意點(diǎn)
MYSQL實(shí)例安全問題:假如 password 類型為字符串,查詢條件為 int 0 則會(huì)匹配上.
MYSQL實(shí)例
mysql> select * from test;
+----+-------+-----------+
| id | name | password |
+----+-------+-----------+
| 1 | test1 | password1 |
| 2 | test2 | password2 |
+----+-------+-----------+
2 rows in set (0.00 sec)
mysql> select * from test where name = 'test1' and password = 0;
+----+-------+-----------+
| id | name | password |
+----+-------+-----------+
| 1 | test1 | password1 |
+----+-------+-----------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+-----------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'password1' |
+---------+------+-----------------------------------------------+
1 row in set (0.00 sec)
MYSQL實(shí)例相信上面的例子,一些機(jī)靈的同學(xué)可以發(fā)現(xiàn)其實(shí)上面的例子也可以做sql注入.
MYSQL實(shí)例假設(shè)網(wǎng)站的登錄那塊做的比較挫,使用下面的方式:
MYSQL實(shí)例
SELECT * FROM users WHERE username = '$_POST["username"]' AND password = '$_POST["password"]'
MYSQL實(shí)例如果username輸入的是a' OR 1='1
,那么password隨便輸入,這樣就生成了下面的查詢:
MYSQL實(shí)例
SELECT * FROM users WHERE username = 'a' OR 1='1' AND password = 'anyvalue'
MYSQL實(shí)例就有可能登錄系統(tǒng).其實(shí)如果攻擊者看過了這篇文章,那么就可以利用隱式轉(zhuǎn)化來進(jìn)行登錄了.如下:
MYSQL實(shí)例
mysql> select * from test;
+----+-------+-----------+
| id | name | password |
+----+-------+-----------+
| 1 | test1 | password1 |
| 2 | test2 | password2 |
| 3 | aaa | aaaa |
| 4 | 55aaa | 55aaaa |
+----+-------+-----------+
4 rows in set (0.00 sec)
mysql> select * from test where name = 'a' + '55';
+----+-------+----------+
| id | name | password |
+----+-------+----------+
| 4 | 55aaa | 55aaaa |
+----+-------+----------+
1 row in set, 5 warnings (0.00 sec)
MYSQL實(shí)例之所以出現(xiàn)上述的原因是因?yàn)椋?/p>
MYSQL實(shí)例
mysql> select '55aaa' = 55;
+--------------+
| '55aaa' = 55 |
+--------------+
| 1 |
+--------------+
1 row in set, 1 warning (0.00 sec)
mysql> select 'a' + '55';
+------------+
| 'a' + '55' |
+------------+
| 55 |
+------------+
1 row in set, 1 warning (0.00 sec)
MYSQL實(shí)例下面通過一些例子來復(fù)習(xí)一下上面的轉(zhuǎn)換規(guī)則:
MYSQL實(shí)例
mysql> select 1+1;
+-----+
| 1+1 |
+-----+
| 2 |
+-----+
1 row in set (0.00 sec)
mysql> select 'aa' + 1;
+----------+
| 'aa' + 1 |
+----------+
| 1 |
+----------+
1 row in set, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'aa' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
MYSQL實(shí)例把字符串“aa”和1進(jìn)行求和,得到1,因?yàn)椤癮a”和數(shù)字1的類型不同,MySQL官方文檔告訴我們:
MYSQL實(shí)例???? When an operator is used with operands of different types, type conversion occurs to make the operands compatible.
MYSQL實(shí)例查看warnings可以看到隱式轉(zhuǎn)化把字符串轉(zhuǎn)為了double類型.但是因?yàn)樽址欠菙?shù)字型的,所以就會(huì)被轉(zhuǎn)換為0,因此最終計(jì)算的是0+1=1
MYSQL實(shí)例上面的例子是類型不同,所以出現(xiàn)了隱式轉(zhuǎn)化,那么如果我們使用相同類型的值進(jìn)行運(yùn)算呢?
MYSQL實(shí)例
mysql> select 'a' + 'b';
+-----------+
| 'a' + 'b' |
+-----------+
| 0 |
+-----------+
1 row in set, 2 warnings (0.00 sec)
mysql> show warnings;
+---------+------+---------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b' |
+---------+------+---------------------------------------+
2 rows in set (0.00 sec)
MYSQL實(shí)例是不是有點(diǎn)郁悶?zāi)?
MYSQL實(shí)例之所以出現(xiàn)這種情況,是因?yàn)?為算術(shù)操作符arithmetic operator 這樣就可以解釋為什么a和b都轉(zhuǎn)換為double了.因?yàn)檗D(zhuǎn)換之后其實(shí)就是:0+0=0了.
MYSQL實(shí)例再看一個(gè)例子:
MYSQL實(shí)例
mysql> select 'a'+'b'='c';
+-------------+
| 'a'+'b'='c' |
+-------------+
| 1 |
+-------------+
1 row in set, 3 warnings (0.00 sec)
mysql> show warnings;
+---------+------+---------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'b' |
| Warning | 1292 | Truncated incorrect DOUBLE value: 'c' |
+---------+------+---------------------------------------+
3 rows in set (0.00 sec)
MYSQL實(shí)例現(xiàn)在就看也很好的理解上面的例子了吧.a+b=c結(jié)果為1,1在MySQL中可以理解為TRUE,因?yàn)?a'+'b'的結(jié)果為0,c也會(huì)隱式轉(zhuǎn)化為0,因此比較其實(shí)是:0=0也就是true,也就是1.
MYSQL實(shí)例第二個(gè)需要注意點(diǎn)就是防止多查詢或者刪除數(shù)據(jù)
MYSQL實(shí)例
mysql> select * from test;
+----+-------+-----------+
| id | name | password |
+----+-------+-----------+
| 1 | test1 | password1 |
| 2 | test2 | password2 |
| 3 | aaa | aaaa |
| 4 | 55aaa | 55aaaa |
| 5 | 1212 | aaa |
| 6 | 1212a | aaa |
+----+-------+-----------+
6 rows in set (0.00 sec)
mysql> select * from test where name = 1212;
+----+-------+----------+
| id | name | password |
+----+-------+----------+
| 5 | 1212 | aaa |
| 6 | 1212a | aaa |
+----+-------+----------+
2 rows in set, 5 warnings (0.00 sec)
mysql> select * from test where name = '1212';
+----+------+----------+
| id | name | password |
+----+------+----------+
| 5 | 1212 | aaa |
+----+------+----------+
1 row in set (0.00 sec)
MYSQL實(shí)例?上面的例子本意是查詢id為5的那一條記錄,結(jié)果把id為6的那一條也查詢出來了.我想說明什么情況呢?有時(shí)候我們的數(shù)據(jù)庫表中的一些列是varchar類型,但是存儲(chǔ)的值為‘1123'這種的純數(shù)字的字符串值,一些同學(xué)寫sql的時(shí)候又不習(xí)慣加引號(hào).這樣當(dāng)進(jìn)行select,update或者delete的時(shí)候就可能會(huì)多操作一些數(shù)據(jù).所以應(yīng)該加引號(hào)的地方別忘記了.
MYSQL實(shí)例關(guān)于字符串轉(zhuǎn)數(shù)字的一些說明
MYSQL實(shí)例
mysql> select 'a' = 0;
+---------+
| 'a' = 0 |
+---------+
| 1 |
+---------+
1 row in set, 1 warning (0.00 sec)
mysql> select '1a' = 1;
+----------+
| '1a' = 1 |
+----------+
| 1 |
+----------+
1 row in set, 1 warning (0.00 sec)
mysql> select '1a1b' = 1;
+------------+
| '1a1b' = 1 |
+------------+
| 1 |
+------------+
1 row in set, 1 warning (0.00 sec)
mysql> select '1a2b3' = 1;
+-------------+
| '1a2b3' = 1 |
+-------------+
| 1 |
+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> select 'a1b2c3' = 0;
+--------------+
| 'a1b2c3' = 0 |
+--------------+
| 1 |
+--------------+
1 row in set, 1 warning (0.00 sec)
MYSQL實(shí)例從上面的例子可以看出,當(dāng)把字符串轉(zhuǎn)為數(shù)字的時(shí)候,其實(shí)是從左邊開始處理的.
MYSQL實(shí)例總結(jié)
MYSQL實(shí)例以上就是這篇文章的全部內(nèi)容了,如果你有其他更好的例子,或者被隱式轉(zhuǎn)化坑過的情況,歡迎分享.希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流.
轉(zhuǎn)載請(qǐng)注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/3276.html