mysql update不支持子查询更新
先看示例:
SELECT uin,account,password,create_user_uin_tree FROM sys_user
结果:
表中的create_user_uin_tree标识该条记录由谁创建。
创建新用户时,根据当前登录用户的uin及新创建的用户uin,有如下SQL:
select concat(ifNULL(create_user_uin_tree,concat('_',2,'_')),'|_','',"_") from sys_user where uin=2
结果:
那么修改的create_user_uin_tree的标识SQL为:
update sys_user set create_user_uin_tree=(select concat(ifNULL(temp.create_user_uin_tree,concat('_',2,'_')),'|_','',"_") from sys_user temp where temp.uin=2) where uin = 97;
报错信息:
Error Code: 1093. You can't specify target table 'sys_user' for update in FROM clause 0.000 sec
原因:
mysql中不支持子查询更新,准确的说是更新的表不能在set和where中用于子查询。那串英文错误提示就是说,不能先select出同一表中的某些值,再update这个表(在同一语句中)。
两种方法:
1、select from 修改为子查询方式
2、inner join
方法1:子查询方式
调整了下SQL:
update sys_user set
create_user_uin_tree=(select temp.tree from (select concat(ifNULL(create_user_uin_tree,concat('_',97,'_')),'|_','',"_") as tree from sys_user where uin=97) temp) where uin = 98;
我将作为子集,
select concat(ifNULL(create_user_uin_tree,concat('_',97,'_')),'|_','',"_") as tree from sys_user where uin=97) temp
然后再
select temp.tree from(子集)
子集,这样就不会 select 和 update 都是同一个表。致此问题得到完美解决。
方法2:inner join
参考:
在sql server中,我们可是使用以下update语句对表进行更新:
update a set a.xx= (select yy from b) where a.id = b.id ;
但是在mysql中,不能直接使用set select的结果,必须使用inner join:
update a inner join (select yy from b) c on a.id =b.id set a.xx = c.yy
MySQL不允许SELECT FROM后面指向用作UPDATE的表,有时候让人纠结。当然,有比创建无休止的临时表更好的办法。本文解释如何UPDATE一张表,同时在查询子句中使用SELECT.
假设我要UPDATE的表跟查询子句是同一张表,这样做有许多种原因,例如用统计数据更新表的字段(此时需要用group子句返回统计值),从某一条记录的字段update另一条记录,而不必使用非标准的语句,等等。举个例子:
错误提示是:ERROR 1093 (HY000): You can't specify target table 'apples' for update in FROM clause. MySQL手册UPDATE documentation这下面有说明 : “Currently, you cannot update a table and select from the same table in a subquery.”
在这个例子中,要解决问题也十分简单,但有时候不得不通过查询子句来update目标。好在我们有办法。
既然MySQL是通过临时表来实现FROM子句里面的嵌套查询,那么把嵌套查询装进另外一个嵌套查询里,可使FROM子句查询和保存都是在临时表里进行,然后间接地在外围查询被引用。下面的语句是正确的:
CREATE TABLE `user2` (
`id` INT(11) NOT NULL,
`name` VARCHAR(50) DEFAULT NULL,
`device` VARCHAR(40) DEFAULT NULL,
`memo` VARCHAR(40) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO `user2`(`id`,`name`,`device`,`memo`) VALUES (1,'duan','',NULL),(2,'liang','',NULL),(3,'hou','',NULL); //子查询
UPDATE user2 SET memo=(SELECT temp.dc FROM (SELECT device AS dc FROM user2 WHERE id=2) temp) WHERE id = 2;
//列=列
UPDATE user2 SET memo=device;
//join
如果你想了解更多其中的机制,请阅读MySQL Internals Manual相关章节。
没有解决的问题
一个常见的问题是,IN()子句优化废品,被重写成相关的嵌套查询,有时(往往?)造成性能低下。把嵌套查询装进另外一个嵌套查询里并不能阻止它重写成相关嵌套,除非我下狠招。这种情况下,最好用JOIN重构查询(rewrite such a query as a join)。
另一个没解决的问题是临时表被引用多次。“装进嵌套查询”的技巧无法解决这些问题,因为它们在编译时被创建,而上面讨论的update问题是在运行时。
另外一个示例:交换两条记录中的字段值方法
表test:
id priority
1 1
2 2
方法一:
mysql语句如下:
update question set sort=(case when id=7 then (select a.sort from (select tmp.* from question tmp) a
where a.id=8) when id=8 then (select a.sort from (select tmp.* from question tmp) a where a.id=7) end)
where id=7 or id=8;
方法二:
update question as q1 join question as q2 on (q1.id=7 and q2.id = 8)
or(q1.id = 8 and q2.id=7)
set q1.sort = q2.sort,q2.sort=q1.sort;
mysql update不支持子查询更新的更多相关文章
- mysql sql_safe_updates 不支持子查询的更新。
考虑到开发人员有时候不小心误更新数据,要求线上库的 MySQL 实例都设置 sql_safe_updates=1 来避免没有索引的 update.delete. 结果有一天开发发现下面的一个SQL 没 ...
- mysql update/delete in 子查询改写
#子查询(不支持) limit ,); #改写 limit ,) t ; #子查询(不支持) delete from `user` where id in ( ) ); #改写 delete from ...
- update 中实现子查询
mysql 在update中实现子查询的方式 当使用mysql条件更新时--最先让人想到的写法 UPDATE buyer SET is_seller=1 WHERE uid IN (SELECT ...
- mysql 在update中实现子查询的方式
当使用mysql条件更新时--最先让人想到的写法 UPDATE buyer SET is_seller=1 WHERE uid IN (SELECT uid FROM seller) 此语句是错误的, ...
- MySQL锁类型以及子查询锁表问题、解锁
MySQL中select * for update锁表的范围 MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主 ...
- php+mysql 内联接 和 子查询
INNER JOIN(内连接):取得两个表中存在连接匹配关系的记录 $sql="SELECT * FROM subject as a INNER JOIN e_user as b ON a. ...
- MySQL使用存储过程代替子查询
摘要: 出处:黑洞中的奇点 的博客 http://www.cnblogs.com/kelvin19840813/ 您的支持是对博主最大的鼓励,感谢您的认真阅读.本文版权归作者所有,欢迎转载,但请保留该 ...
- sql根据子查询更新语句
update … from语句 测试环境准备 create table #table1 ( id ) ); go create table #table2 ( id ) ); go , , , , , ...
- 数据库Mysql的学习(六)-子查询和多表操作
)*0.05 WHERE card_id ='20121xxxxxx'; //子查询就是一个嵌套先计算子查询 SELECT * FROM borrow WHERE book_id =(SELECT b ...
随机推荐
- java 项目中每个jar包的作用总结
别人的总结 1.Struts2 1)commons-fileupload :2)common-io:文件上传 3)commons-lang:它扩展了标准 java.langAPI ArrayUtils ...
- 手把手教你安装SSL证书升级https
是不是觉得别人网站前面的小绿锁很好看? 而且,Google官方也正式承认过https是影响搜索排名的一个因素,那么如何将自己的网站全面升级为https呢?今天的内容就介绍一下如何将部署在Nginx的W ...
- 中文乱码之myEclipse项目导入时中文乱码(待)
方法1:检查默认的编码是否设置成utf-8. 步骤如图: window——>preferences... 若Text file encoding 中的编码为 Other == UTF-8 ,则已 ...
- 回溯法之n皇后问题
package main import ( "fmt" "math" ) //判断第k行的某一列放置是否合法 func check(col []int, k i ...
- JS中跨域问题
这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...
- UML类图(三)-------实例
实例分析1——登录模块 某基于C/S的即时聊天系统登录模块功能描述如下: 用户通过登录界面(LoginForm)输入账号和密码,系统将输入的账号和密码与存储在数据库(User)表中的用户信息进行比较, ...
- ADO.NET入门教程(一) 初识ADO.NET
摘要 作为.NET框架最重要的组件之一,ADO.NET扮演着应用程序与数据交互的重要的角色.本文将从宏观的角度来探讨ADO.NET,和大家一起了解ADO.NET来龙去脉以及ADO.NET的主要组成部分 ...
- 51nod 1672 贪心/队列
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1672 1672 区间交 基准时间限制:1 秒 空间限制:131072 K ...
- 05-THREE.JS 产生大雾的效果
<!DOCTYPE html> <html> <head> <title></title> <script src="htt ...
- python--基本代码规范
python代码规范:一.标识符 所谓的标识符就是对变量.常量.函数.类等对象起的名字 python语言在任何场景都严格区分大小写!!! python对于标识符的命名有如下规定: 第一个字符必须是字母 ...