好久没来园子了,转眼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. es6 export与export default 的区别

    相同点: 均可用于导出常量.函数.文件.模块等 不同点: 1.在一个文件中export可以有多个,但export default 只能有一个: export var firstName = 'Mich ...

  2. SpringBoot2+WebSocket之聊天应用实战(优化版本)

    背景 之前再SpringBoot2.0集成WebSocket,实现后台向前端推送信息中已经进行过一次demo,而这次的demo更加明确,优化了相关代码,为IM而生 前提 前提当然是导入相关的包,以及配 ...

  3. Node.js ORM框架Sequlize之表间关系

    Sequelize模型之间存在关联关系,这些关系代表了数据库中对应表之间的主/外键关系.基于模型关系可以实现关联表之间的连接查询.更新.删除等操作.本文将通过一个示例,介绍模型的定义,创建模型关联关系 ...

  4. Ink——一款使用React风格开发命令行界面应用(CLI App)的nodejs工具

    Github: https://github.com/vadimdemedes/ink Ink introduction: React for CLIs. Build and test your CL ...

  5. Azure 中虚拟机的计划内维护

    Azure 定期执行更新,以提高虚拟机的主机基础结构的可靠性.性能及安全性. 此类更新包括修补宿主环境(例如操作系统.虚拟机监控程序以及主机上部署的各种代理)中的软件组件.升级网络组件以及硬件解除授权 ...

  6. Sql server的Merge语句,源表中如果有重复数据会导致执行报错

    用过sql server的Merge语句的开发人员都应该很清楚Merge用来做表数据的插入/更新是非常方便的,但是其中有一个问题值得关注,那就是Merge语句中的源表中不能出现重复的数据,我们举例来说 ...

  7. 三种方法实现java调用Restful接口

    1,基本介绍 Restful接口的调用,前端一般使用ajax调用,后端可以使用的方法比较多, 本次介绍三种: 1.HttpURLConnection实现 2.HttpClient实现 3.Spring ...

  8. 转:Sql Server中的表访问方式Table Scan, Index Scan, Index Seek

    0.参考文献 Table Scan, Index Scan, Index Seek SQL SERVER – Index Seek vs. Index Scan – Diffefence and Us ...

  9. 【转】Java学习---算法那些事

    [更多参考] LeetCode算法 每日一题 1: Two Sum ----> 更多参考[今日头条--松鼠游学] 史上最全的五大算法总结 Java学习---7大经典的排序算法总结实现 程序员都应 ...

  10. 匿名访问windows server 2008 R2 文件服务器的共享

    匿名访问windows server 2008 R2 文件服务器的共享 匿名访问windows 2008 R2 文件服务器的共享,七步:第一步 取消简单文件共享:第二步 设置需要共享的文件夹every ...