在使用INSERT语句的时候,一般都是使用它向数据库中一条条的插入数据,比如:


INSERT INTO MyTable(FId,FName,FAge)VALUES(1,"John",20)

但是有时我们可能需要将数据批量插入表中,比如创建一个和T_ReaderFavorite表结构完全相同的表T_ReaderFavorite2,然后将T_ReaderFavorite 中的输入复制插入到T_ReaderFavorite2表。

首先我们创建T_ReaderFavorite2 表:


MYSQL,MSSQLServer,DB2: CREATE TABLE T_ReaderFavorite2 (FCategoryId INT,FReaderId INT) Oracle: CREATE TABLE T_ReaderFavorite2 (FCategoryId NUMBER (10),FReaderId NUMBER (10))

按照普通的实现思路,我们需要编写如下的宿主语言代码:


rs = ExecuteQuery("SELECT * from T_ReaderFavorite"); while(rs.next()) { int categoryId = rs.get("FCategoryId"); int readerId = rs.get("FReaderId"); Execute("INSERT INTo T_ReaderFavorite2(FCategoryId,FReaderId) VALUES(?,?)", categoryId, readerId); }

在宿主语言中逐条读取T_ReaderFavorite表中的记录,然后将它们逐条插入T_ReaderFavorite2表中。这样的处理方式能够正确的完成要求的功能,而且由于目前T_ReaderFavorite 表中的数据量非常少,所以这样处理速度上也没有什么影响。但是如果T_ReaderFavorite 表中有大量的数据的话,由于每插入一条数据都要执行两次数据库操作,所以这种处理方式效率非常低,因此必须采用其他的处理方式。

除了INSERT……VALUES……这种用法外,INSERT语句还支持另外一种语法,那就是INSERT……SELECT……,采用这种使用方式可以将SELECT语句返回的结果集直接插入到目标表中,因为这一切都是都数据库内部完成的,所以效率非常高。下面看一下使用INSERT……SELECT……来实现将T_ReaderFavorite中的输入复制插入到T_ReaderFavorite2表,SQL语句如下:


INSERT INTO T_ReaderFavorite2(FCategoryId,FReaderId) SELECT FCategoryId,FReaderId FROM T_ReaderFavorite

这里使用SELECT FCategoryId,FReaderId FROM T_ReaderFavorite将T_ReaderFavorite表中的数据读出,然后使用INSERT INTO T_ReaderFavorite2(FCategoryId,FReaderId)将检索结果插入到T_ReaderFavorite2 表中,注意上下的列顺序必须是一一对应的。

执行完毕我们后我们查看T_ReaderFavorite2 表中的内容:


FCategoryId FReaderId 1 1 5 2 2 3 3 4 5 5 1 6 1 7 4 8 6 9 5 10 2 11 2 12 1 12 3 1 1 3 4 4

可以看到T_ReaderFavorite表中的数据已经被正确的复制到T_ReaderFavorite2 表中了。

使用INSERT……SELECT……不仅能够实现简单的将一个表中的数据导出到另外一个表中的功能,还能在将输入插入目标表之前对数据进行处理,比如下面的SQL 语句用于将T_ReaderFavorite表中的数据复制到T_ReaderFavorite2 表中,但是如果T_ReaderFavorite表中的FReaderId 列的值大于10,则将FReaderId 的值减去FCategoryId 的值后再复制到T_ReaderFavorite2 表中。编写如下的SQL语句:


INSERT INTO T_ReaderFavorite2(FCategoryId,FReaderId) SELECT FCategoryId,(CASE WHEN FReaderId<=10 THEN FReaderId ELSE FReaderId- FCategoryId END) FROM T_ReaderFavorite

这里在SELECT 语句中使用CASE 函数来实现对数据插入前的处理。执行完毕我们后我们查看T_ReaderFavorite2 表中的内容:


FCategoryId FReaderId 1 1 5 2 2 3 3 4 5 5 1 6 1 7 4 8 6 9 5 10 2 9 2 10 1 11 3 1 1 3 4 4

使用这种插入前的数据处理可以完成诸如“将数据从A表导出到B表,并且将B表的主键全部加上bak前缀”、“将A公司的所有员工插入到我们的会员表,自动导入所有的客户信息,并且为其自动生成会员编号”等复杂的任务。

因为可以在插入目标表前可以对数据进行处理,所以INSERT……SELECT……语句不局限于同结构表间的数据插入,也可以实现异构表见输入的插入。假设要将所有会员爱好的图书统一增加“小说”,也就是为T_Reader 表中的每个读者都在T_ReaderFavorite表中创建一条FCategoryId等于1 的记录,实现SQL语句如下:


INSERT INTO T_ReaderFavorite(FCategoryId,FReaderId) SELECT 1,FId FROM T_Reader

SELECT语句从T_Reader表中检索所有的读者信息,并且将第一列设定为固定值1,而将第二列设定为读者的主键,执行完毕查看T_ReaderFavorite表中的内容:


FCategoryId FReaderId 1 1 5 2 2 3 3 4 5 5 1 6 1 7 4 8 6 9 5 10 2 11 2 12 1 12 3 1 1 3 4 4 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 1 11 1 12

数据被正确的插入了,但是仔细查看T_ReaderFavorite表中的内容,不难发现其中有重复的数据,比如FCategoryId等于1、FReaderId等于1的记录出现了两次,这就出现了数据冗余,必须修改SQL语句防止这种情况的发生。也就是在将输入插入T_ReaderFavorite表之前要检查T_ReaderFavorite表中是否已经存在了同样的数据。

在继续进行之前请首先清空T_ReaderFavorite 表中的数据,然后执行开头的T_ReaderFavorite表数据的初始化代码。

首先需要在SELECT语句中添加WHERE子句,这个WHERE子句检查每个读者是否有Story的爱好,即是否存在图书分类主键为1的的爱好,只有没有的时候才返回记录:


SELECT 1,FId FROM T_Reader WHERE NOT EXISTS ( SELECT * FROM T_ReaderFavorite WHERE T_ReaderFavorite. FCategoryId=1 AND T_ReaderFavorite. FReaderId= T_Reader.FId )

执行这个子查询片段,执行完毕我们就能在输出结果中看到下面的执行结果:


FId 1 2 1 4 1 5 1 8 1 9 1 10 1 11

可以看到检索出的确实是还没有以Story做为爱好的读者,所以编写下面的SQL语句来执行数据的插入:


INSERT INTO T_ReaderFavorite(FCategoryId,FReaderId) SELECT 1,FId FROM T_Reader WHERE NOT EXISTS ( SELECT * FROM T_ReaderFavorite WHERE T_ReaderFavorite. FCategoryId=1 AND T_ReaderFavorite. FReaderId= T_Reader.FId )

执行完毕查看T_ReaderFavorite表中的内容:


FCategoryId FReaderId 1 1 5 2 2 3 3 4 5 5 1 6 1 7 4 8 6 9 5 10 2 11 2 12 1 12 3 1 1 3 4 4 1 2 1 4 1 5 1 8 1 9 1 10 1 11

可以看到表中的数据没有重复的了,即使重复执行这个SQL 语句也都不会添加新的记录,因为这个SQL语句已经对数据的重复做了检查。

子查询在INSERT语句中的应用的更多相关文章

  1. 子查询在DELETE语句中的应用

    子查询在DELETE 中唯一可以应用的位置就是WHERE 子句,使用子查询可以完成复杂的数据删除控制.其使用方式与SELECT 语句中的子查询基本相同,而且也可以使用相关子查询等高级的特性.下面的SQ ...

  2. 子查询在UPDATE 语句中的应用

    在UPDATE语句中可以在更新列表中以及WHERE语句使用子查询.下面演示一个将图书的出版日期全部更新为所有图书中的最新出版日期,SQL语句如下: UPDATE T_Book SET FYearPub ...

  3. sql子查询在insert、update、delete中的应用

    子查询可以应用在INSERT.UPDATE以及DELETE等语句中,合理的使用子查询将能够简化功能的实现并且极大的提高SQL语句执行的效率 用到的表: CREATE TABLE `t_readerfa ...

  4. sql子查询 嵌套SELECT语句

    嵌套SELECT语句也叫子查询,一个 SELECT 语句的查询结果能够作为另一个语句的输入值.子查询不但能够出现在Where子句中,也能够出现在from子句中,作为一个临时表使用,也能够出现在sele ...

  5. 输出,变量的使用,子查询,逻辑语句,循环,case..when..then..end多分支语句,Exists(判断存在)

    --------------输出----------------print 'hello world'--以文本形式输出select 'hello world'--以网格形式输出,也可以设置成以文本形 ...

  6. where EXISTS (子查询)多对多中通过中间表查对方列表

    用户表A,小组表B,小组和用户是多对多关系,中间有个中间表M 已知 小组 id 即teamId ,想知道这个小组中的用户列表信息,可以如下写sql: select * from A a where E ...

  7. MySQL Execution Plan--IN子查询对UPDATE语句影响

    问题描述 在系统中发现一条执行时间为为44652.060734秒(12.5小时)的慢SQL,SQL语句为: UPDATE ob_internal_task SET OPERATE_STATUS WHE ...

  8. Mybatis笔记 – insert语句中主键的返回

    在DBMS中可以使用insert语句显示指定自增主键值,但Mybatis中不可,即使指定了也无效,可以使用特殊的方式返回主键. 一.自增主键返回         mysql自增主键执行insert提交 ...

  9. SQL insert语句中插入带有特殊符号

    1.插入数据库字符串中海油单引号,需要转义处理,例如插入“I‘m OK!” SQL语句: INSERT INTO tableTest(FileTXT) VALUES('I''m OK!') 2.如果S ...

随机推荐

  1. 【BZOJ】1578: [Usaco2009 Feb]Stock Market 股票市场

    [题意]给定s个股票和d天,给出价格矩阵s*d,每天可以买入或卖出整数倍股票,初始资金m,求最大利益.m<=200000,s<=50,d<=10. [算法]完全背包 [题解]关键在于 ...

  2. 【BZOJ】1602:[Usaco2008 Oct]牧场行走

    [算法]最近公共祖先(LCA) [题解] 点x,y到最近公共祖先z的距离之和相当于x,y到根的距离减去两倍z到根的距离, 即ans=dis[x]+dis[y]-2*dis[z] 记得边数组要开两倍!! ...

  3. HDU 2577 How to Type (字符串处理)

    题目链接 Problem Description Pirates have finished developing the typing software. He called Cathy to te ...

  4. 对vue中 默认的 config/index.js:配置的详细理解 -【以及webpack配置的理解】-config配置的目的都是为了服务webpack的配置,给不同的编译条件提供配置

    当我们需要和后台分离部署的时候,必须配置config/index.js: 用vue-cli 自动构建的目录里面  (环境变量及其基本变量的配置) var path = require('path') ...

  5. 制作Solaris系统的USB启动盘

    制作方法: 1. wget http://192.168.2.5/surefiler-installer/2011-12-09/devel-2011.12.9.tgz 2. cd /root tar  ...

  6. ie6下双边距的问题

    1.ie6双边距情况 <div class="red"></div> <div class="blue"></div& ...

  7. PHP 接入(第三方登录)QQ 登录 OAuth2.0 过程中遇到的坑

    前言 绝大多数网站都集成了第三方登录,降低了注册门槛,增强了用户体验.最近看了看 QQ 互联上 QQ 登录的接口文档.接入 QQ 登录的一般流程是这样的:先申请开发者 -> 然后创建应用(拿到一 ...

  8. centos7下opencv的安装

    os:centos7 opencv:opencv3.0.0 for linux reference:http://www.cnblogs.com/xixixing/p/6096057.html det ...

  9. C语言inline函数(转)

    原文链接:http://blog.csdn.net/yuan1125/article/details/6225993 1  inline只是个编译器建议,编译器不一定非得展开Inline函数. 例如: ...

  10. FineReport——FS

    FR除了能够实现对报表等的二次开发,还能实现对决策系统的操作: FS.Trans.signOut() 退出决策平台系统 FS.tabPane._doCloseTab(FS.tabPane._getSe ...