将查询结果插入到现有表中
在数据库日常维护工作中,我们可能经常需要把某个查询结果插入到现有的表中。如需要把两张表进行合并、需要把另外一张报纸能够符合条件的的记录插入到现有的表中、需要把另外一张表中的某些字段重新整理后插入到现有的表中等等。但是,我们都知道在数据库中对此进行操作,不想Excel表格那么方便,通过选择、复制、粘贴即可以完成工作表之间的合并。在数据库中,不能够对列直接进行复制与粘贴的操作。那么在数据库中能否有简单而有效的解决措施呢?其实在SQLServer数据库中,灵活使用insert into Select(插入结果查询)语句就可以实现这个需求。
如现在由于公司人事部门合并后需要把数据库中的USER_A中的数据复制到表USE_B中。那么就可以利用如下的语句来实现:
Insert into USER_B (ad_user_id,Value,name,manager_id)
Select ad_user_id,Value,name,manager_id from USER_A Where( manager_id =100001)
通过如上这条简单的insert into select语句就可以把某一张表中符合条件的记录插入到目标表中。不过这条语句虽然比较简单,但是其中的条条框框仍然有很多。具体的来说,在使用这条语句的时候,需要遵守如下的这些条条框框。
一、需要指定源表中需要复制的列。
有时候可能复制与被复制的表表结构不同。如需要把表A中的name(英文名字)字段复制到表B中的name2(中文名字)中。此时原有复制表与被复制表中字段的名称不同,为此需要在上面的语句中,把所需要复制列名称一一列举出来。另外可能只需要把被复制表中的部分列复制到目的表总,此时也有显示的指名所需要复制的列。注意复制对象与目标对象都需要列出,以免发生张冠李戴的现象。笔者在使用这条语句的时候,不管任何情况,及时两者表格中的内容完全一致,笔者也习惯在语句中把字段的名称一一的列出。虽然这会增加一定的工作量,但是却可以提高这条语句执行的准确性。简而言之,就是需要在语句中指定源表zhon纲要复制其内容的列;指定目标表总要向其中复制数据的目标列。即使两这个表中的这些列名称相同,也最好能够显示的指定。此时数据库管理员不能够偷懒,否则的话很容易导致数据插入错误,而一切要重头再来。
二、存储数据时的顺序。
如果现在在源表中有一万条符合条件的记录要保存到目的表中,那么这些记录在数据库中存储的顺序应该是什么呢?默认情况下,其存储的数据顺序就是查询结果所得到的顺序。在没有采用排序语句的情况下,其实就是源表中实际存储的顺序(一般按记录创建的先后顺序来保存)。不过有时候可能这个排序顺序不怎么合理。笔者在认为,最好对需要插入的结果进行恰当的排序,这有利于提高插入记录的查询效率。如在牧地中,可能对员工编号设置了索引;或者在目的表中查询员工的信息是按员工编号来排序的。那么在目的表中插入数据的时候,最好能够按员工的编号来进行排列。是顺序还是逆序排列要跟目的表中保持一致。如此的话,插入数据后进行查询的话,如需要查询所有后来插入的结果,那么就不需要对其进行重新排序。因为存储的时候就是按照员工编号来插入,那么查询出来的数据也是按照员工编号来的。可见,为需要插入的数据设置合理的排序顺序,这有利于提高以后查询的性能。故笔者建议,为了提高数据库的性能,最好在插入数据的时候利用Order BY语句指定插入数据时的顺序。虽然这不是强制性的,但是笔者建议各位数据库管理员还是要这么做。
三、指定复制行的条件。
需要把某张表中的记录复制到另外一张表中,往往需要指定复制行的条件。也就是说,往往不会把源表中所有的记录都复制到目的表中。如现在需要把员工信息A表中的数据复制到员工信息B表中。可是由于员工离职或者其他的原因,员工信息A表中的记录可能有些已经作废掉了。如果把A表中的数据不加过滤就直接把全部记录都一成不变的复制到B表中,那显然会给B表增加不少的垃圾数据。为此在复制数据到目的表的表的时候,企业用户可能只需要把现在还在职的员工信息复制到B表中。此似,在使用上面的语句时,就需要利用Where条件来限制需要复制的行。如一般在数据库系统设计的时候,都会在表中加入一个isactive类似的控制字段,表示当前记录是否有效。当员工离职时,不会删除这个员工的信息,而是会把其设置为不活跃。在数据库表中反应出来的就是这个字段为N。为此,在上面的语句中,要把isactive列对应的值为N的记录去掉。所以如果在表与表合并的时候,需要根据一定的规则来过滤数据的话,则可以在语句中加入Where语句来进行限制。这个限制虽然不是必须的,但是却可以避免把一些垃圾数据也导入到新表中。
虽然数据库管理员可以先把所有的记录先都复制到目的表中,然后再利用delete语句进行删除。但是笔者并不赞成这么做。一方面这么做会额外的增加工作量;其次也会对目标表中的数据产生破坏。因为在目标表中执行delete语句中,如果条件设置不当,那么很有可能把目标表中的数据也删除了。所以说,复制记录后再进行删除,这个操作会带来一定的风险。一不小心,就会破坏源表中的数据。其实,在复制的时候,在语句中加入Where限制语句就可以轻而易举的避免这种风险。既然如此,数据库管理员还有什么理由还需要在事后再冒这个风险呢?
四、插入结果时要注意数据的兼容性。
当把记录插入到目的表中,需要注意源表中的内容必须与目标中的列兼容。这主要包含两个方面的含义。一是数据类型要兼容,二是其字段的大小需要兼容。如源表中的name字段的长度为22;而目的表中这个字段的长度只有20。则在执行以上的语句时,就很可能因为数据长度过长而导致复制失败。除了要注意这个字段长度的兼容之外,还需要注意的是数据库在复制的过程中会对某些数据类型进行自动的转换。如源表中员工编号这个字段可能是采取流水号编号,为此数据库中的字段类型可能就是整数型。而在目的表中,对于员工编号采用部门号(字符)+流水号的形式,那么在数据库表中其采用的就是字符类型格式。现在需要把源表中的员工编号的字段内容复制到目的表中,是可以的。虽然两者的数据类型不同,但是把整数型的数据复制到字符型的字段中,这是允许的。也就是说,他们是兼容的。但是需要注意的是,复制过去后,原先的整数型数据在目的表中会以字符型数据来存储,而不是整数型数据。为此如果后来因为其他原因,需要把目的表中的数据再复制到源表中时,就会发生错误。因为字符型数据是无法在整数型数据类型中进行存储。所以说,在数据库中所谓的兼容往往是单向的。这一点在进行记录复制的时候,需要特别的当心。
另外有些数据类型可能是不兼容的,那么在复制数据的时候,数据库管理员需要采用数据类型转换函数对其进行强制转换。如某个字段虽然存储的都是数字,但是其数据库中的数据类型是字符型的。此时需要把字符型的数据(全部都是数字)复制到整数型的字段中,则需要利用强制转换函数先对数据类型进行转换,然后再进行复制。这也是解决数据类型不一致的一个有效措施。
五、执行复制时的注意事项。
在使用这条语句的时候,需要注意其跟普通的insert语句不同。通常情况下,如果利用Insert语句插入记录的时候,如果发现插入的记录有问题,则可以通过撤销执行插入操作(在没有递交事务之前)来撤销插入的操作。但是使用insert into 语句进行表与表之间合并记录的时候,则是不能够执行撤销操作的。为此为了数据的安全,最好在执行insert into语句之前,对数据库来一个手工的完全备份。如此当这个操作有问题的时候,则可以通过恢复数据库来解决由此带来的问题。
另外,在执行这个语句的时候,最好先执行一下其SELECT子句,看看其查询出来的结果是否符合用户的需要。当这个查询语句设计准确后,再把其跟Insert into 语句结合起来使用,这个方法可以提高表记录合并的准确率。虽然中间多了一个查询的步骤,但是对于数据的准确性来说,这一个步骤还是值得的。
转http://database.ctocio.com.cn/488/8861488_1.shtml