Insert是T-sql中常用语句,Insert INTO table(field1,field2,...) values(value1,value2,...)这种形式的在应用程序开发中必不可少。但我们在开发、测试过程中,经常会遇到需要表复制的情况,如将一个table1的数据的部分字段复制到table2中,或者将整个table1复制到table2中,这时候我们就要使用SELECT INTO 和 INSERT INTO SELECT 表复制语句了。

1.INSERT INTO SELECT语句

语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Table1

要求目标表Table2必须存在,由于目标表Table2已经存在,所以我们除了插入源表Table1的字段外,还可以插入常量。示例如下:

   --1.创建测试表
    create TABLE Table1
    (
        a varchar(10),
        b varchar(10),
        c varchar(10),
        CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
        (
            a ASC
        )
    ) ON [PRIMARY]     create TABLE Table2
    (
        a varchar(10),
        c varchar(10),
        d int,
        CONSTRAINT [PK_Table2] PRIMARY KEY CLUSTERED
        (
            a ASC
        )
    ) ON [PRIMARY]
    GO
    --2.创建测试数据
    Insert into Table1 values('赵','asds','90')
    Insert into Table1 values('钱','asds','100')
    Insert into Table1 values('孙','asds','80')
    Insert into Table1 values('李','asds',null)
    GO
    select * from Table2     --3.INSERT INTO SELECT语句复制表数据
    Insert into Table2(a, c, d) select a,c,5 from Table1
    GO     --4.显示更新后的结果
    select * from Table2
    GO
    --5.删除测试表
    drop TABLE Table1
    drop TABLE Table2

2.SELECT INTO FROM语句

语句形式为:SELECT vale1, value2 into Table2 from Table1

要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中。示例如下:

   --1.创建测试表
    create TABLE Table1
    (
        a varchar(10),
        b varchar(10),
        c varchar(10),
        CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED
        (
            a ASC
        )
    ) ON [PRIMARY]
    GO     --2.创建测试数据
    Insert into Table1 values('赵','asds','90')
    Insert into Table1 values('钱','asds','100')
    Insert into Table1 values('孙','asds','80')
    Insert into Table1 values('李','asds',null)
    GO     --3.SELECT INTO FROM语句创建表Table2并复制数据
    select a,c INTO Table2 from Table1
    GO     --4.显示更新后的结果
    select * from Table2
    GO
    --5.删除测试表
    drop TABLE Table1
    drop TABLE Table2

今天听同事介绍oracle到mysql的数据migration,他用了Insert into ..... on duplicate key update ...,我当时就想怎么不用Replace呢,于是回来就仔细查了下,它们果然还是有区别的,看下面的例子吧:

1 Replace into ...
1.1 录入原始数据

mysql> use test;
Database changed
mysql> 

mysql> CREATE TABLE t1 SELECT 1 AS a, 'c3' AS b, 'c2' AS c;
ALTER TABLE t1 CHANGE a a INT PRIMARY KEY AUTO_INCREMENT ;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> INSERT INTO t1 SELECT 2,'2', '3';
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0
mysql> insert into t1(b,c) select 'r2','r3';
Query OK, 1 row affected (0.08 sec)
Records: 1  Duplicates: 0  Warnings: 0

1.2 开始replace操作
mysql> REPLACE INTO t1(a,b) VALUES(2,'a') ;
Query OK, 2 rows affected (0.06 sec)

【】看到这里,replace,看到这里,a=2的记录中c字段是空串了,
所以当与key冲突时,replace覆盖相关字段,其它字段填充默认值,可以理解为删除重复key的记录,新插入一条记录,一个delete原有记录再insert的操作

1.3 但是不知道对主键的auto_increment有无影响,接下来测试一下:

  1. mysql> insert into t1(b,c) select 'r4','r5';
  2. Query OK, 1 row affected (0.05 sec)
  3. Records: 1  Duplicates: 0  Warnings: 0
  4. mysql> select * from t1;
  5. +---+----+----+
  6. | a | b  | c  |
  7. +---+----+----+
  8. | 1 | c3 | c2 |
  9. | 2 | a  |    |
  10. | 3 | r2 | r3 |
  11. | 5 | r4 | r5 |
  12. +---+----+----+
  13. 4 rows in set (0.00 sec)

【】从这里可以看出,新的自增不是从4开始,而是从5开始,就表示一个repalce操作,主键中的auto_increment会累加1.
所以总结如下:
Replace:

当没有key时,replace相当于普通的insert.
当有key时,可以理解为删除重复key的记录,在保持key不变的情况下,delete原有记录,再insert新的记录,新纪录的值只会录入replace语句中字段的值,其余没有在replace语句中的字段,会自动填充默认值。

2.1 ok,再来看Insert into ..... on duplicate key update,

  1. mysql> insert into t1(a,b) select '3','r5' on duplicate key update b='r5';
  2. Query OK, 2 rows affected, 1 warning (0.19 sec)
  3. Records: 1  Duplicates: 1  Warnings: 1
  4. mysql> select * from t1;
  5. +---+----+----+
  6. | a | b  | c  |
  7. +---+----+----+
  8. | 1 | c3 | c2 |
  9. | 2 | a  |    |
  10. | 3 | r5 | r3 |
  11. | 5 | r4 | r5 |
  12. +---+----+----+
  13. 4 rows in set (0.00 sec)

【】a=5时候,原来的c值还在,这表示当key有时,只执行后面的udate操作语句.

2.2 再检查auto_increment情况。

  1. mysql> insert into t1(a,b) select '3','r5' on duplicate key update b='r5';
  2. Query OK, 2 rows affected, 1 warning (0.19 sec)
  3. Records: 1  Duplicates: 1  Warnings: 1
  4. mysql> select * from t1;
  5. +---+----+----+
  6. | a | b  | c  |
  7. +---+----+----+
  8. | 1 | c3 | c2 |
  9. | 2 | a  |    |
  10. | 3 | r5 | r3 |
  11. | 5 | r4 | r5 |
  12. +---+----+----+
  13. 4 rows in set (0.00 sec)
  14. mysql> insert into t1(b,c) select 'r6','r7';
  15. Query OK, 1 row affected (0.19 sec)
  16. Records: 1  Duplicates: 0  Warnings: 0
  17. mysql> select * from t1;
  18. +---+----+----+
  19. | a | b  | c  |
  20. +---+----+----+
  21. | 1 | c3 | c2 |
  22. | 2 | a  |    |
  23. | 3 | r5 | r3 |
  24. | 5 | r4 | r5 |
  25. | 7 | r6 | r7 |
  26. +---+----+----+
  27. 5 rows in set (0.00 sec)

【】从这里可以看出,新的自增不是从6开始,而是从7开始,就表示一个Insert .. on deplicate udate操作,主键中的auto_increment也跟replace一样累加1.

2.3 再看下当没有key的时候,insert .. on deplicate update的情况

  1. mysql> insert into t1(a,b,c) select '33','r5','c3' on duplicate key update b='r5';
  2. Query OK, 1 row affected, 1 warning (0.23 sec)
  3. Records: 1  Duplicates: 0  Warnings: 1
  4. mysql> select * from t1;
  5. +----+----+----+
  6. | a  | b  | c  |
  7. +----+----+----+
  8. |  1 | c3 | c2 |
  9. |  2 | a  |    |
  10. |  3 | b5 | r3 |
  11. |  5 | r4 | r5 |
  12. |  7 | r6 | r7 |
  13. |  9 | s6 | s7 |
  14. | 33 | r5 | c3 |
  15. +----+----+----+
  16. 7 rows in set (0.00 sec)

看a=33的记录,ok,全部录入了。

3 总结从上面的测试结果看出,相同之处:
(1),没有key的时候,replace与insert .. on deplicate udpate相同。
(2),有key的时候,都保留主键值,并且auto_increment自动+1
不同之处:有key的时候,replace是delete老记录,而录入新的记录,所以原有的所有记录会被清除,这个时候,如果replace语句的字段不全的话,有些原有的比如例子中c字段的值会被自动填充为默认值。
      而insert .. deplicate update则只执行update标记之后的sql,从表象上来看相当于一个简单的update语句。
      但是实际上,根据我推测,如果是简单的update语句,auto_increment不会+1,应该也是先delete,再insert的操作,只是在insert的过程中保留除update后面字段以外的所有字段的值。
   
 所以两者的区别只有一个,insert .. on deplicate udpate保留了所有字段的旧值,再覆盖然后一起insert进去,而replace没有保留旧值,直接删除再insert新值。
 从底层执行效率上来讲,replace要比insert .. on deplicate update效率要高,但是在写replace的时候,字段要写全,防止老的字段数据被删除。

个人倾向与用Replace。

 

replace和insert的语句插入(转)的更多相关文章

  1. mysql数据库中,通过一条insert into语句,同时插入多个值

    需求描述: 今天在看一本mysql的书籍,发现一个mysql中insert into好用的技巧,就是通过 1条insert into语句,插入多行数据,而不是多个insert into语句.在此记录下 ...

  2. mysql数据库使用insert语句插入中文数据报错

    在mysql的命令行模式中,通过insert语句插入中文数据的时候报错,类似于下面这样: Incorrect string value: '\xE7\x8F' for column 'name' at ...

  3. oracle一条语句插入多个值的方法

    今天在实践过程中遇到一个问题, 我想往数据库插入多条数据时,使用了如下语句: insert into 表1 (字段1,字段2) values (1,2),(2,3),(3,4); 这条语句在mysql ...

  4. SQL INSERT INTO 语句

    SQL Order By SQL update INSERT INTO 语句 INSERT INTO 语句用于向表格中插入新的行. 语法 INSERT INTO 表名称 VALUES (值1, 值2, ...

  5. ACCESS的System.Data.OleDb.OleDbException: INSERT INTO 语句的语法错误

    一直用的是SQL 数据库,突然改用Access了,使用起来就是没有SQL 顺畅,老是出来些意想不到的错误.今天用Access做的网站程序进行添加数据,调试了一下午,总是异常…… 提示ACCESS的Sy ...

  6. Insert Into 语句的语法错误

    错误示意: 一开始程序是: 改正: 一条很简单的插入语句竟然会报错,然而直接在数据库的查询中执行中却没有问题,这个问题困扰了不少时间. 数据库使用的是ACCESS,INSERT INTO语句为inse ...

  7. insert into 语句的三种写法

    insert into 语句的三种写法 方式1. INSERT INTO t1(field1,field2) VALUES (v001,v002);            // 明确只插入一条Valu ...

  8. Oracle INSERT ALL 语句介绍

    描述 Oracle INSERT ALL 语句用来用一个 INSERT 语句添加多行.该行可以只使用一个SQL命令插入到一个表或多个表. 语法 Oracle INSERT ALL 语法如下: INSE ...

  9. 8.INSERT INTO 语句 UPDATE 语句

    1. INSERT INTO 语句 INSERT INTO 语句用于向表格中插入新的行. 语法 INSERT INTO 表名称 VALUES (值1, 值2,....) INSERT INTO Per ...

随机推荐

  1. HDU5739 Fantasia 树形dp + 点双缩点

    这个题当时打多校的时候有思路,但是代码能力差,没有写出来 事后看zimpha巨巨的题解,看了觉得基本差不多 核心思路:就是找出割点,然后变成森林,然后树形dp就可以搞了 关键就在重新构图上,缩完点以后 ...

  2. IOS color 颜色值比较

    /生成采样对照颜色(黑色) UIColor* sampleColor = [UIColor colorWithRed:(0/255.0f) green:(0/255.0f)  blue:(0/255. ...

  3. 【LeetCode 208】Implement Trie (Prefix Tree)

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  4. <转>准备Eclips+python+robot framework环境

    关于python: path添加:C:\Python27;C:\Python27\Scripts; 新加一项:  PYTHON_HOME    C:\Python27 再不行的话,加一个用户变量: P ...

  5. 今天工作遇到要发短信(ios)的功能,于是随手记录了一下

    ios中发送短信有两种 1.程序外调用系统短信 2.程序内调用系统发短信 第一种比较简单,直接调用url就可以了 oc下的代码为 [[UIApplication sharedApplication] ...

  6. 在fedora20下面手动为自己的安装程序创建桌面图标

    (博客园-番茄酱原创) 在/usr/share/applications/下面创建destktop文件,用于产生桌面图标 创建文件:touch android-eclipse.desktop 编辑文件 ...

  7. java StreamTokenizer使用

    注意:用JAVA解题一般用Scanner类来进行输入,但对时间要求严格的题,用它可能会超时,我.解POJ1823的时候就遇到这样的问题,后改用StreamTokenizer类进行输入,就过了.看来后者 ...

  8. 【Hadoop代码笔记】Hadoop作业提交之Child启动reduce任务

    一.概要描述 在上篇博文描述了TaskTracker启动一个独立的java进程来执行Map任务.接上上篇文章,TaskRunner线程执行中,会构造一个java –D** Child address ...

  9. Codeforces 381 简要题解

    做的太糟糕了...第一题看成两人都取最优策略,写了个n^2的dp,还好pre-test良心(感觉TC和CF的pretest还是很靠谱的),让我反复过不去,仔细看题原来是取两边最大的啊!!!前30分钟就 ...

  10. 关于tomcat不支持put方式的解决方式

    在jetty中是支持put方式操作的,在tomcat中默认是不支持的,解决方式很简单,在web.xml中添加一个过滤器即可. <filter> <filter-name>htt ...