3.2 用INSERT语句添加数据
INSERT语句的基本语法类似下面这样:
INSERT [INTO] <表> [(列的列表)] VALUES (数据值)
来看语法中的各个部分:
l INSERT是操作语句。它告诉SQL Server要利用该语句来完成什么,所有出现在这一关键字后面的事物都只是为了说明操作细节的。
l INTO关键字几乎是无足轻重的。它存在的唯一目的是让整个语句更具可读性。虽然该关键字完全是可选的,但是,为了加入它的这种特别的目的——使语句更加易读,我强烈推荐使用它。
l 接下来是要向其中插入数据的表。
l 截至目前为止,事情都十分简单明了,而现在要讲述的部分——列的列表,则多了一些难度。显示的列的列表(在这里具体说明要接收数据的列)是可选的,但若不提供的话,你必须加倍小心。如果不明确给出列的列表,那么,认为INSERT语句中的每一个值与表中同样顺序处的每一个列是相匹配的(第一个值对应第一个列,第二个值对应第二个列,依此类推)。另外,必须按顺序为所有既不允许空值又没有默认值的列提供一个值,直至到达最后一个这样的列(很快将接触到更多相关的内容)。总之,这将是一列或多列的列表,在语句的下一部分为这些列提供数据。
l 最后,给出要插入的数据值。有两种方式提供值:显示给出值,以及从SELECT语句中导出值。
为了提供要插入的值,我们在关键字VALUES后引入值的列表,列表以逗号分隔并包含在圆括号中。值的列表中项的数目必须列的列表中列的数目完全匹配。每一个值的数据类型必须同与它(依照顺序)对应的列的类型相匹配,或者能隐式地转换成列的类型。
关于“是否应该明确地为每一个列声明值”的问题,我确实推荐每次都说明所有的列——哪怕只是使用DEFAULT关键字或显式指定NULL。DEFAULT将告知SQL Server使用该列上的默认值(如果列上没有定义默认值,则会得到一个错误)。
这样做的好处是代码极具可读性——明确表明了当前正在做什么。另外,显式地说明每一个列将减少错误,同时,若以后修改了表的结构,语句仍然可用的可能性也得以提高。
举例来说,INSERT语句可能会是如下这样:
![]()
正如前面说过的,除非给出了不同的列的列表(稍后将看到如何提供列的列表),否则,所有的值都必须按照表中列的定义顺序给出。例外的情况是,当表中有一个标识列时,该列会被跳过。
查看表HumanResources.JobCandidate的定义,将看到它的第一列是名为JobCandidateID的标识列。既然这是一个标识列,那么系统会自动为该列生成一个值,因而可以跳过此列。
理论上(鉴于你是在阅读本书而非《SQL Server 2005基础教程》),我们已经差不多知晓了这些知识,眼下只是做一个回顾,因此,这里直接提出几个概念。
l 完全跳过标识列(系统将为我们填入标识值);
l 给出实际的值(为EmployeeID列提供的值1,以及为Resume显式声明的NULL值);
l 通过DEFAULT关键字(ModifiedDate列)显式告诉服务器使用那一列的默认值。
现在,对语句进行修改,向指定的列中插入值:
![]()
注意,这里依然跳过了标识列。此外,我们只是显式给出了列名,其他没什么不同。
INSERT INTO ... SELECT语句
前面这种“一次插入一行”的方式用起来很不错,但是,如果想要一次插入一批数据呢?在本书的讲述过程中,会在不同的场合多次碰到这种需求。然而,眼下只集中考虑这种情况,即要插入到表中的数据是从其他数据源中选取出来的,这些其他的数据源有:
l 数据库中的另一个表;
l 同一台服务器上完全不同的数据库;
l 来自另一个SQL Server的异类查询或其他数据;
l 来自同一表中的数据(通常,这种情况下是在SELECT语句中做某种数学的或其他类型的调整)。
所有这些都能通过INSERT INTO...SELECT来完成。该语句的语法是由我们已经讨论过的两种语句组合而来的——INSERT语句以及SELECT语句。其语法类似下面这样:
INSERT INTO <表名>
[<列列表>]
<SELECT语句>
由SELECT语句产生的结果集成为要在INSERT语句中插入的数据。
接下来,通过把一些数据选取到某种形式的临时表中来了解该语句,当进入到高级的代码编写时,会发现总是在做这样的事情。这里,先声明一个表变量,然后把Orders表中的数据行填充到表变量中:
下面的代码块称为脚本。这些代码构成了一个批处理。第10章将详细地研究批处理。

![]()

这些语句将产生类似下面的结果:

第一行(4 row(s) affected)是运行INSERT...SELECT语句所产生的结果——SELECT语句返回了4行,因此有4行数据插入到了表中。接着直接用一个SELECT语句来验证插入。
注意,如果试图单独在@MyTable上运行SELECT(即在脚本之外),将得到一个错误。@MyTable是声明的一个变量,只存在于声明它的批处理中。当声明它的批处理结束后,它会被自动销毁掉。
此外,值得注意的是,我们也可以使用临时表——它们本质上是相同的,只是起作用的方式不同。在第10章和第11章中将再次讨论临时表和表变量。






