MySQL update set 和 and的區(qū)別
最近接到一個(gè)奇怪的咨詢,update 語(yǔ)句執(zhí)行沒(méi)有報(bào)錯(cuò),但是沒(méi)有更新數(shù)據(jù),具體有問(wèn)題的語(yǔ)句類似于如下形式:
update test.stu set cname = ’0’ and math = 90 and his = 80 where id = 100;原因分析
直觀上看,這個(gè) update 語(yǔ)句的語(yǔ)法是有問(wèn)題的,正常更新多列數(shù)據(jù)的語(yǔ)法應(yīng)該是用逗號(hào),類似于如下形式:
update test.stu set cname = ’0’,math = 90,his = 80 where id = 100;
直接用 and 第一反應(yīng)其實(shí)是會(huì)報(bào)語(yǔ)法錯(cuò)誤,不太像是能正常執(zhí)行的。那么基于騰訊云數(shù)據(jù)庫(kù) MySQL,實(shí)際構(gòu)造一個(gè)簡(jiǎn)單的場(chǎng)景,嘗試復(fù)現(xiàn)一下這個(gè)問(wèn)題。
SQL 語(yǔ)句如下:
CREATE TABLE `stu` ( `id` int(11) NOT NULL, `sname` varchar(16) NOT NULL, `cname` varchar(8) DEFAULT NULL, `math` int(11) NOT NULL, `eng` int(11) DEFAULT NULL, `his` int(11) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;insert into stu values(100,’sam’,’0’,90,88,83);insert into stu values(101,’jhon’,’1’,97,82,81);insert into stu values(102,’mary’,’2’,87,89,92);insert into stu values(103,’adam’,’2’,87,89,92);
然后分別試一試正常的 update 語(yǔ)句和使用 and 的 update 語(yǔ)句,看一下實(shí)際的運(yùn)行結(jié)果:
mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update test.stu set cname = ’0’ and math = 90 and his = 80 where id = 100;Query OK, 0 rows affected (0.00 sec)Rows matched: 1 Changed: 0 Warnings: 0mysql> select * from stu;+-----+-------+-------+------+------+------+| id | sname | cname | math | eng | his |+-----+-------+-------+------+------+------+| 100 | sam | 0 | 90 | 88 | 83 || 101 | jhon | 1 | 97 | 82 | 81 || 102 | mary | 2 | 87 | 89 | 92 || 103 | adam | 2 | 87 | 89 | 92 |+-----+-------+-------+------+------+------+4 rows in set (0.00 sec)mysql> update test.stu set cname = ’0’,math = 90,his = 80 where id = 100;Query OK, 1 row affected (0.01 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from stu;+-----+-------+-------+------+------+------+| id | sname | cname | math | eng | his |+-----+-------+-------+------+------+------+| 100 | sam | 0 | 90 | 88 | 80 || 101 | jhon | 1 | 97 | 82 | 81 || 102 | mary | 2 | 87 | 89 | 92 || 103 | adam | 2 | 87 | 89 | 92 |+-----+-------+-------+------+------+------+4 rows in set (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.01 sec)mysql>
可以看到這兩個(gè)語(yǔ)句確實(shí)都不會(huì)報(bào)錯(cuò),且?guī)?and 的 update 語(yǔ)句匹配到了具體的行(Rows matched: 1),但是沒(méi)有修改數(shù)據(jù)(Changed: 0),標(biāo)準(zhǔn)語(yǔ)法下的 update 語(yǔ)句倒是正常修改了數(shù)據(jù)。
由此可見(jiàn),MySQL 在語(yǔ)法上,并不認(rèn)為 and 這個(gè)用法是錯(cuò)誤的,那么說(shuō)明 MySQL 用另外的方式“解讀”了這個(gè)語(yǔ)句。最容易想到的,就是 MySQL 是不是在 set 的時(shí)候,把 and 解釋成了邏輯運(yùn)算符,而不是英文意義上的“和”?而且 cname 的取值本來(lái)就是 0,也符合數(shù)據(jù)庫(kù)處理 bool 數(shù)據(jù)時(shí)的行為(用 0 和 1 代替 False 和 True)。
驗(yàn)證起來(lái)很簡(jiǎn)單,換個(gè) cname 不為 0 的數(shù)據(jù) update 一下就可以了:
mysql> select * from stu;+-----+-------+-------+------+------+------+| id | sname | cname | math | eng | his |+-----+-------+-------+------+------+------+| 100 | sam | 0 | 90 | 88 | 83 || 101 | jhon | 1 | 97 | 82 | 81 || 102 | mary | 2 | 87 | 89 | 92 || 103 | adam | 2 | 87 | 89 | 92 |+-----+-------+-------+------+------+------+4 rows in set (0.00 sec)mysql> begin;update test.stu set cname = ’0’ and math = 90 and his = 80 where id = 101;Query OK, 0 rows affected (0.00 sec)Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from stu;+-----+-------+-------+------+------+------+| id | sname | cname | math | eng | his |+-----+-------+-------+------+------+------+| 100 | sam | 0 | 90 | 88 | 83 || 101 | jhon | 0 | 97 | 82 | 81 || 102 | mary | 2 | 87 | 89 | 92 || 103 | adam | 2 | 87 | 89 | 92 |+-----+-------+-------+------+------+------+4 rows in set (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.00 sec)
從結(jié)果來(lái)看,MySQL 修改 cname 的值為 0,說(shuō)明確實(shí)是當(dāng)成邏輯運(yùn)算符來(lái)處理了,仔細(xì)分析這個(gè)語(yǔ)句,會(huì)發(fā)現(xiàn) MySQL 按照如下方式來(lái)處理:
set cname = (’0’ and math = 90 and his = 80)
math 和 his 的取值是根據(jù) where 條件篩選的行來(lái)決定的,實(shí)際對(duì)應(yīng)到上面測(cè)試的場(chǎng)景,會(huì)變成如下的邏輯判斷:
’0’ and 97 = 90 and 81 = 80
PS:需要注意,即便是字符型的數(shù)據(jù) 0,也會(huì)被當(dāng)做 False。
解決方案目前并不能通過(guò) sql_mode 或者其他參數(shù)的形式來(lái)阻止這種帶 and 的 update 語(yǔ)句,因此這一類問(wèn)題的隱蔽性比較強(qiáng)。建議在開(kāi)發(fā)的時(shí)候,利用封裝好的框架,或者加強(qiáng)代碼或者 SQL review 來(lái)避免這個(gè)問(wèn)題。
PS:騰訊云數(shù)據(jù)庫(kù) MySQL 也會(huì)有類似的問(wèn)題,需要警惕。
以上就是MySQL update set 和 and的區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于MySQL update set 和 and的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. 什么是Access數(shù)據(jù)庫(kù)2. Sql Server 壓縮數(shù)據(jù)庫(kù)日志文件的方法3. Microsoft Office Access刪除表記錄的方法4. 關(guān)于oracle日期函數(shù)的介紹和使用5. Mybatis環(huán)境搭建及文件配置過(guò)程解析6. 提綱挈領(lǐng)Oracle數(shù)據(jù)庫(kù)災(zāi)難防護(hù)技術(shù)7. DB2 V9.5工作負(fù)載管理之閾值(THRESHOLD)8. Mysql服務(wù)添加 iptables防火墻策略的方案9. MySQL DDL 引發(fā)的同步延遲該如何解決10. MariaDB中1045權(quán)限錯(cuò)誤導(dǎo)致拒絕用戶訪問(wèn)的錯(cuò)誤解決方法

網(wǎng)公網(wǎng)安備