sql语句之表间字段值复制遇到的一些问题--基于mysql
好久没来园子了,转眼2017已经到3月份了,前段时间一直忙没时间写博客(其实是自己懒),感觉内心好惭愧。昨天临下班前,技术老大突然对我说要改下表结构,问我能不能实现将一个表的字段值复制到另外一个表的某个字段中去,感觉这好拗口,其实就是表间字段值复制。于是,昨晚加了会儿班百度了下然后自己在本地测试了下,还真弄出来了,下面就把这个sql语句记下来,以备忘。
1,背景和需求
两张表a_user和b_user结构如下:
a_user
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id_a | int(11) | NO | PRI | NULL | auto_increment|
| a_name| varchar(45)| YES | | NULL | |
+--------+-------------+------+-----+---------+----------------+
b_user
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| id_b | int(11) | NO | PRI | NULL |auto_increment|
| a_id | int(11) | NO | MUL | NULL | |
| b_name| varchar(45)| YES | | NULL | |
+--------+-------------+------+-----+---------+----------------+
两表间关系:表b_user的a_id外键参考表a_user的主键id_a。
记录分别如下:
a_user
+------+--------+
| id_a | a_name |
+------+--------+
| 1 | |
| 2 | |
| 3 | |
| 4 | |
+------+--------+
b_user
+------+------+--------+
| id_b | a_id | b_name |
+------+------+--------+
| 1 | 1 | 张三 |
| 2 | 2 | 李四 |
| 3 | 2 | 李四 |
| 4 | 3 | 王五 |
| 5 | 3 | 王五 |
| 6 | 3 | 王五 |
| 7 | 4 | 赵六 |
| 8 | 4 | 赵六 |
+------+------+--------+
需求:将b_user表中b_name字段的值复制到a_user表中的a_name。
2,百度和解决遇到的问题
百度了下,发现用这个sql语句靠点儿谱:
update a_user set a_name = (select b_name from b_user where id_a = a_id);
这个语句大概是指,更新表a_user的a_name字段,将表b_user中b_name字段的值作为值来源,但直接执行上面的语句时mysql会报错如下:
ERROR 1242 (21000): Subquery returns more than 1 row
意思是,update语句期望数据来源行数应该与a_user表中的行数4行是相等的,但是上面的子查询结果却是......,等下,上面的子查询可以执行么?当然不可以。其实上面的子查询也就相当于:
select b_name from b_user left join a_user on a_id = id_a;
但是它返回的结果是8行,与表a_user的行数不同。
(1)剔除数据来源的重复行
那么先解决这个问题,将重复的记录剔除不就可以了么: select distinct a_id, b_name from b_user left join a_user on a_id = id_a; 它返回的结果如下:
+------+--------+
| a_id | b_name |
+------+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 4 | 赵六 |
+------+--------+
结果为2列,如果执行下面的语句它会报错:
update a_user set a_name = (select distinct a_id, b_name from b_user left join a_user on a_id = id_a);
ERROR 1241 (21000): Operand should contain 1 column(s)
那么怎么把上面的结果变为只包含b_name的一列呢?
(2)利用distinct按a_id剔除重复行后多了a_id列
这个也好解决,把子查询再嵌套一下就可以了:
select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t;
好,再试下update语句
update a_user set a_name = (select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t);
ERROR 1242 (21000): Subquery returns more than 1 row
可以看到上面又报了子查询结果与更新行数不一致的问题,奇怪,上面的子查询 select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t; 结果是:
+--------+
| b_name |
+--------+
| 张三 |
| 李四 |
| 王五 |
| 赵六 |
+--------+
不是已经剔除了重复行了吗?
(3)子查询嵌套和sql语句执行顺序
分析下上面的问题:现在有两个子查询select语句,外层的select将内层的select作为数据来源进行查询,内层的select和外层的select单独执行时都可以返回预期的结果,那么为什么执行update时却出现了: ERROR 1242 (21000): Subquery returns more than 1 row ?
下面是我的猜测:update语句的执行是一行一行的,那么当更新第一条记录时,update会期望从select子查询中获取一条对应于第一条记录的数据,也就是update a_user set a_name = 值来源 where id_a = a_id;那么就需要加上where语句来限定:
update a_user set a_name = (select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t where t.a_id = id_a);
这下就可以了,结果如下:
+------+--------+
| id_a | a_name |
+------+--------+
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
| 4 | 赵六 |
+------+--------+
3,结果
先写到这儿吧,最后的语句是
update a_user set a_name = (select b_name from (select distinct a_id, b_name from b_user left join a_user on a_id = id_a) t where t.a_id = id_a);
说实话,心里还是没底。这里涉及到了sql嵌套查询、sql语句执行顺序、update语句执行过程等sql知识,总之,靠百度和自己误打误撞算是弄出了条sql,不过我只是在本地上测试了下,没有在生产环境下用,对于这条sql的执行效率啥的更是没有概念,先做个记录,以后再研究下。希望有专门搞数据库的同学能够指点下。
参考资料:
如何批量修改一列的值?把另一张表的某个字段对应的赋到这张表的某一字段中。
完
sql语句之表间字段值复制遇到的一些问题--基于mysql的更多相关文章
- Access sql语句创建表及字段类型
创建一张空表: Sql="Create TABLE [表名]" 创建一张有字段的表: Sql="Create TABLE [表名]([字段名1] MEMO NOT NUL ...
- Access sql语句创建表及字段类型(转)
http://www.cnblogs.com/hnyei/archive/2012/02/23/2364812.html 创建一张空表: Sql="Create TABLE [表名]&quo ...
- SQL语句添加删除修改字段及一些表与字段的基本操作
用SQL语句添加删除修改字段 1.增加字段 alter table docdsp add dspcode char(200)2.删除字段 ALTER TABLE table_NA ...
- 用SQL语句添加删除修改字段、一些表与字段的基本操作、数据库备份等
用SQL语句添加删除修改字段 1.增加字段 alter table docdsp add dspcode char(200) 2.删除字段 ALTER TABLE table_NAME DROP CO ...
- SQL语句 在一个表中插入新字段
SQL语句 在一个表中插入新字段: alter table 表名 add 字段名 字段类型 例: alter table OpenCourses add Audio varchar(50)alter ...
- SQL语句 删除表user 中字段name 内容重复的记录,
public class T01 { public static void main(String[] args) { int j=4; j=j+=j-=j*=j; System.out.printl ...
- SQL语句添加删除修改字段[sql server 2000/2005]
用SQL语句添加删除修改字段1.增加字段 alter table docdsp add dspcodechar(200)2.删除字段 ALTER TABLE table_NAME ...
- SQL语句添加删除修改字段
用SQL语句添加删除修改字段1.增加字段 alter table docdsp add dspcodechar(200)2.删除字段 ALTER TABLE table_NAME ...
- SQL语句之表操作
SQL语句系列 1.SQL语句之行操作 2.SQL语句之表操作 3.SQL语句之数据库操作 4.SQL语句之用户管理 写在前面 在上一篇博文里面我整理了“行”级别的操作,分别是“增(insert).删 ...
随机推荐
- IntelliJ idea 备份与恢复
为了防止突然断电或者电脑突然关机导致idea恢复出厂设置,需要定期备份配置. 一.备份 File---Export Settings 将settings.jar 文件导入到C:\Users\xutin ...
- <Android 基础(三十五)> RecyclerView多类型Item的正确实现姿势
简介 RecyclerView是我们开发过程中经常使用到的一个元素,原生的RecyclerView.Adapter基本上可以满足一般的需求,关于RecyclerView的基础介绍请移步: Recycl ...
- Linux awk命令常见使用方法介绍
Linux awk命令常见使用方法介绍 By:授客 QQ:1033553122 awk运行方式有三种,其中常用的为命令行方式 awk [-F field_separator] '{patter ...
- Android 2018最新的三方库
文章出处https://blog.csdn.net/qq_32368129/article/details/78749880 1.MaterialStepperView 它是用Material Des ...
- Android--播放Gif的取巧办法
由于做的项目,要有个动画的等待效果,第一时间想到的就是Gif(懒,省事),但是试了好多据说能播放Gif的控件,也写过,但是放到魅族手机上就是不能播放,所有就想了个招,既然Gif能在浏览器上播放,那an ...
- 用sparkR, 分析上亿条订单数据的脚本。
上周我们这个10人的小团队开发的推荐拉新系统, 日拉新人数已接近4万人.过去几个月这个系统从无到有, 拉新从日增几千稳步增长到日增几万, 同事们几个月来,每天工作13个小时以上,洗澡时间都没有, 有时 ...
- Oracle EBS INV 查询物料无值 ECO
查找物料的时候报错 没有输入值 解决方法: 针对FORM做trace 多查看几个生成的trace 搜索 MTL_SYSTEM_ITEMS_b 的信息 查看到最后面的语句(一般可直接查看) 看SQL 哪 ...
- 光杆mdf文件的导入
场景,准备学习SSAS的时候,按照教程在微软下载了示例数据库AdventureWorksDW2012,下载来才发现只有一个mdf文件. 正好今天群里有位兄弟也碰到差不多的问题,客户数据库里的ldf文件 ...
- mysql client之init-command
If the server is a replication master and you want to avoid replicating the content to replication s ...
- InfoPath读取List到重复表
标题设置好了 添加一个按钮 更改ID 点击编写代码 然后添加引用 并更改下域的名字 添加如下代码 public void LoadBtn_Clicked(object sender, Clicked ...