1 場景復現
- MySQL: 5.7.24-27
- 表結構
(兩張獨立的表)
[表 RRR1]
CREATE TABLE `RRR1` (
`R1` float NOT NULL COMMENT 'R1',
`R2` float NOT NULL COMMENT 'R2'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='RRR1';
[表 Person11]
CREATE TABLE `Person11` (
`CSSJY111` varchar(3) DEFAULT NULL COMMENT '測試數據元011',
`CSSJY107` int(3) DEFAULT NULL COMMENT '測試數據元007',
`CSSJY106` int(3) DEFAULT NULL COMMENT '測試數據元006',
`CSSJY112` datetime DEFAULT NULL COMMENT '測試數據元012',
`CSSJY103` varchar(10) DEFAULT NULL COMMENT '測試數據元003',
`CSSJY113` blob COMMENT '測試數據元013',
`CSSJY104` varchar(10) DEFAULT NULL COMMENT '測試數據元004',
`CSSJY108` varchar(10) DEFAULT NULL COMMENT '測試數據元008',
`CSSJY102` varchar(10) DEFAULT NULL COMMENT '測試數據元002',
`CSSJY109` varchar(10) DEFAULT NULL COMMENT '測試數據元009',
`CSSJY101` varchar(10) DEFAULT NULL COMMENT '測試數據元101',
`CSSJY110` date DEFAULT NULL COMMENT '測試數據元010',
`CSSJY105` int(3) DEFAULT NULL COMMENT '測試數據元005'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='個人信息';
- 異常SQL
DELETE FROM
CJ_TEST.`RRR1`
WHERE `R1` IN (
SELECT * FROM (
SELECT `R1` FROM CJ_TEST.`RRR1` WHERE `R1` IN (
SELECT `CSSJY111` FROM (
SELECT `CSSJY111` FROM `CJ_TEST`.`Person11` ORDER BY `CSSJY112` ASC, `CSSJY111` LIMIT 3
) ttt -- 中間表 ttt
)
) B WHERE B.R1 = 1 -- 中間表 B
)
報異常:
[Err] 1292 - Truncated incorrect DOUBLE value: 'dc5'
翻譯: [錯誤] 1292 - 數據截斷:截斷不正確的雙精度值:'dc5'
注: MySQL數據庫 必須帶中間表 ttt 和 B,否則 查詢會失敗
MySQL數據庫中 帶中間表 可避免異常:[Err] 1093 - You can't specify target table 'tableName' for update in FROM clause
FROM clause : FROM 子句
(翻譯: 你不能在DELETE/UPDATE這類修改操作的FROM子句中指定目標表——tableName。)
"不能先select出同一表中的某些值,再update這個表(在同一語句中)"
"不能在同一表中查詢的數據作為同一表的更新數據"
"注意,這個問題只出現於mysql,mssql和Oracle不會出現此問題。" (博主尚未驗證此結論)
原因: DELETE/UPDATE (修改)操作 表tableName時,其FROM子句的實際操作表是 FROM子句內的虛表(結果集)
解決辦法:
1. 在select外邊套一層括號"( 原SQL )",讓數據庫認為你不是查同一表的數據作為同一表的更新數據
2. 將select的結果集臨時設置為中間表——`select * from ( 原select的結果集 ) TMP`,讓修改操作的FROM對象為中間表
詳見:MySQL之You can't specify target table for update in FROM clause解決辦法 - CSDN
2 原因分析
源字段與目標字段的類型不一致!!!
異常SQL中:
源字段為 Person11表的CSSJY111字段(varchar(3))
目標字段為 RRR1表的R1字段(float)
3 解決方案
情況1: 源字段值A與目標字段值B的類型不一致
- 解決方案1
修改數據庫表的字段類型。
ALTER TABLE RRR1 MODIFY COLUMN R1 VARCHAR(3);
- 解決方案2
sql_mode
(此方案不太推薦,但迫不得已時亦可使用)
SET SESSION sql_mode = '';
補充/延申: sql_mode的其它操作
select @@GLOBAL.sql_mode;
select @@SESSION.sql_mode; -- STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
情況2: UPDATE的語法錯誤
網絡博客中很多人更多遇到的是此類情況————語法錯誤
例如:update table set A = "a" and B = "b" where id = 1
(報錯)
- 解決方案
原SQL語句的 "and" 換成逗號 ","
update table set A = "a" , B= "b" where id = 1 (正確)
Y 不足之處與反思
1 追根到底,本質上是什么原因導致的此異常? [√]
—— 此問題已解決 於 2020-10-14 21:14

2 sql_mode的配置起到了什么作用? [待解決]
3 為什么這么做可以成功解決? [√]
—— 此問題已基本解決 於 2020-10-14 21:14
X 參考與推薦文獻
- Data truncation: Truncated incorrect DOUBLE value [推薦] - CSDN
- mysql異常:Data truncation: Truncated incorrect DOUBLE value: '2020-03' - 91mszl.com
- MySQL之You can't specify target table for update in FROM clause解決辦法 - CSDN
- mysql的sql_mode設置 - 博客園
- 當使用update語句時出現Data truncation: Truncated incorrect DOUBLE value:??錯誤. - CSDN