项目中有一个功能变动上线,其中有一张表ttt的字段cc,历史数据需要处理,把字段cc中为’xxx’的值替换为'yyy'。

表A结构如下:

CREATE TABLE `ttt` (
`id` bigint NOT NULL,
`aa` int NOT NULL COMMENT 'xxx',
`bb` int(11) NOT NULL COMMENT 'xxx',
`cc` varchar(64) NOT NULL COMMENT 'xxx',
...
PRIMARY KEY (`id`),
UNIQUE KEY `uk_aa_bb_cc` (`aa`,`bb`,`cc`) USING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8

更新sql如下:

UPDATE ttt SET cc='yyy' WHERE cc='xxx';

执行报错:

Duplicate entry 'xx-xx-yyy' for key 'uk_aa_bb_cc'

因为相同的aa、bb下可能已经有cc值为'yyy'的数据了,

比如已有历史数据:

aa bb cc

1 1 xxx

1 1 yyy

这个时候执行更新sql,就会有2条1 1 yyy,由于字段aa、bb、cc因业务属性设置为唯一索引,所以更新失败。

修改更新sql,将有相同yyy的数据排除掉:

UPDATE ttt a SET a.cc='yyy' WHERE a.cc='xxx'
AND NOT EXISTS (SELECT 1 FROM ttt b WHERE a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy');

执行报错:

You can't specify target table 'a' for update in FROM clause

改成IN条件:

UPDATE ttt a SET a.cc='yyy' WHERE a.cc='xxx'
AND NOT IN (SELECT id FROM ttt b WHERE a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy');

也报同样的错。

这个错误在MySQL会出现,在SQLServer、Oracle上没有,意思是:

不能先select出同一表中的某些值,再update这个表(在同一语句中),即不能依据某字段值做判断再来更新某字段的值。

修改sql如下:

UPDATE ttt a SET a.cc='yyy' WHERE a.cc='xxx'
AND a.id NOT IN (
SELECT id FROM(SELECT id FROM ttt b WHERE a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy')c
);

执行还是报错:

Unknown column 'a.aa' in 'where clause'

看来直接嵌套一层查询也不行。

再次修改sql,使用UPDATE JOIN语法:

UPDATE ttt a
LEFT JOIN ttt b ON a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy'
SET a.cc='yyy'
WHERE a.cc='xxx' AND b.id IS NULL

因为需要排除掉相同记录,这里用LEFT JOIN并且条件为IS NULL的方式

再次执行sql成功。

在执行sql前后可以用sql进行数据查询,比如:

查询没有相同aa、bb且ccc仅有'xxx'的数据(即预先验证上面的更新sql影响的数据情况):

SELECT *
FROM ttt a
LEFT JOIN ttt b ON a.aa=b.aa AND a.bb=b.bb AND b.cc='yyy'
WHERE a.cc='xxx' AND b.id IS NULL

查询有相同aa、bb且cc存在xxx、yyy值的数据:

SELECT aa,bb,COUNT(*) FROM ttt
WHERE cc IN('xxx','yyy')
GROUP BY aa,bb
HAVING COUNT(*)>1

通过aa、bb条件查询:

SELECT * FROM ttt WHERE aa='xx' AND bb='yy';

参考:

MySQL 中 You can't specify target table '表名' for update in FROM clause错误解决办法

MySQL update join语句

最新文章

  1. Couchbase的安装步骤
  2. Warning: in_array() expects parameter 2 to be array, string given in D:\wamp\www\suiji.php on line 26
  3. 李洪强iOS经典面试题123
  4. 奥威power-BI 在线体验平台
  5. java 集合(set)
  6. Java使用poi对Execl简单_读和写_操作
  7. windows 安装paramiko模块
  8. 本地搭建开发环境开发redis程序
  9. Compare the value of entity field.
  10. HDU 1025 DP + 二分
  11. openstack创建实例测试步骤
  12. VC2010编写Dll文件(转)
  13. npm install安装时忘记--save解决方法
  14. 利用python 创建XML文件
  15. 垃圾回收机制(GC)
  16. 浅谈Java语言中ArrayList和HashSet的区别
  17. Android studio设置文件头,定制代码注释
  18. WPF: 自动设置Owner的ShowDialog 适用于MVVM
  19. ApplicationContext 配置里dataSource mysql连接数据源,设置ssl和utf-8
  20. 小事牛刀之——python做文件对比

热门文章

  1. vue-cli搭建vue项目环境
  2. 【Hibernate】抓取策略
  3. java入门学习总结_04
  4. Ubuntu系统---安装English版本之后的一些工作
  5. Java字节码方法表与属性表深度剖析
  6. 大数据之路week02 Collection 集合体系收尾(Set)
  7. Spring Bean装配(下)——注解
  8. linux实操_进程管理
  9. Python+request 将获取的url和接口响应时间(timeout)写入到Excel中《八》
  10. C语言I作业12一学期总结