好久没来园子了,转眼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的更多相关文章

  1. Access sql语句创建表及字段类型

    创建一张空表: Sql="Create TABLE [表名]" 创建一张有字段的表: Sql="Create TABLE [表名]([字段名1] MEMO NOT NUL ...

  2. Access sql语句创建表及字段类型(转)

    http://www.cnblogs.com/hnyei/archive/2012/02/23/2364812.html 创建一张空表: Sql="Create TABLE [表名]&quo ...

  3. SQL语句添加删除修改字段及一些表与字段的基本操作

    用SQL语句添加删除修改字段 1.增加字段     alter table docdsp    add dspcode char(200)2.删除字段     ALTER TABLE table_NA ...

  4. 用SQL语句添加删除修改字段、一些表与字段的基本操作、数据库备份等

    用SQL语句添加删除修改字段 1.增加字段 alter table docdsp add dspcode char(200) 2.删除字段 ALTER TABLE table_NAME DROP CO ...

  5. SQL语句 在一个表中插入新字段

    SQL语句 在一个表中插入新字段: alter table 表名 add 字段名 字段类型 例: alter table OpenCourses add Audio varchar(50)alter ...

  6. SQL语句 删除表user 中字段name 内容重复的记录,

    public class T01 { public static void main(String[] args) { int j=4; j=j+=j-=j*=j; System.out.printl ...

  7. SQL语句添加删除修改字段[sql server 2000/2005]

    用SQL语句添加删除修改字段1.增加字段     alter table docdsp    add dspcodechar(200)2.删除字段     ALTER TABLE table_NAME ...

  8. SQL语句添加删除修改字段

    用SQL语句添加删除修改字段1.增加字段     alter table docdsp    add dspcodechar(200)2.删除字段     ALTER TABLE table_NAME ...

  9. SQL语句之表操作

    SQL语句系列 1.SQL语句之行操作 2.SQL语句之表操作 3.SQL语句之数据库操作 4.SQL语句之用户管理 写在前面 在上一篇博文里面我整理了“行”级别的操作,分别是“增(insert).删 ...

随机推荐

  1. 如何获取listview里面的edittext或者RadioGroup的值,涉及到引发的混乱现象

    最近要实现从数据库读数据,该数据对应listview的item布局里面的RadioButton值,并且item布局里面还有EditText的控件. 如何将每一条对应的listview对应值获取出来呢? ...

  2. Adobe Flash Builder 4.6 打开时提示Failed to create the Java Virtual Machine

    最近使用actionscript来编程,用到Adobe Flash Builder 工具,之前一直用着都没事的,今天打开突然就报了这个错误,然后就打不开了 好了,不多说,直接来吧. 首先在你的Adob ...

  3. 移动端采坑:Position: fixed 在Safari上的Bug

    Position: fixed 在IOS上的显示效果 会出现两种情况: 点击fixed定位的元素会出现fixed定位失效导致的元素贴向底部,即position: absolute,bottom: 0p ...

  4. 使用IDEA创建Java Web项目并部署

    前面给大家介绍了IDEA的安装和基本配置,睡觉前Alan再给大家分享一下使用IDEA创建Java Web并部署访问. 打开IDEA,File>New>Project,进入Java Ente ...

  5. Asp.Net Core Docker镜像更新系统从wheezy改为stretch

    之前写过一个在Asp.Net Core里调用System.Drawing.Common绘图的DEMO,部署到Docker里运行,需要更新Asp.Net Core镜像的操作系统. https://www ...

  6. 从零自学Java-2.初步理解Java程序使如何工作的

    1.学习Java应用程序是如何工作的 2.构成一个应用程序 3.向应用程序传递参数 4.学习Java程序是如何组织的 5.在应用程序中创建一个对象 程序Root:输出225的正平方根 package ...

  7. html基础笔记-表单、链接

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- 字符编码U ...

  8. Spring中的destroy-method方法

    1. Bean标签的destroy-method方法 配置数据源的时候,会有一个destroy-method方法 <bean id = "dataSource" class  ...

  9. 【MySQL 5.7 Reference Manual】15.4.2 Change Buffer(变更缓冲)

    15.4.2 Change Buffer(变更缓冲)   The change buffer is a special data structure that caches changes to se ...

  10. .net 页面传参方式总结

    一.使用Querystring Querystring是一种非常简单的传值方式,其缺点就是:安全性低.会把要传送的值显示在浏览器的地址栏中(也就是不需要保密得参数),并且在此方法中不能够传递对象,参数 ...