插入记录

INSERT 将新行添加到表或视图。

语法

INSERT [ INTO]

{ table_name WITH ( < table_hint_limited > [ ...n ] )

| view_name

| rowset_function_limited

}

{ [ ( column_list ) ]

{ VALUES

( { DEFAULT | NULL | expression } [ ,...n] )

| derived_table

| execute_statement

}

}

| DEFAULT VALUES

< table_hint_limited > ::=

{ FASTFIRSTROW

| HOLDLOCK

| PAGLOCK

| READCOMMITTED

| REPEATABLEREAD

| ROWLOCK

| SERIALIZABLE

| TABLOCK

| TABLOCKX

| UPDLOCK

}

参数

[INTO]

一个可选的关键字，可以将它用在 INSERT 和目标表之间。

table_name

将要接收数据的表或 table 变量的名称。

WITH (<table_hint_limited> [...n])

指定目标表所允许的一个或多个表提示。需要有 WITH 关键字和圆括号。不允许有 READPAST、NOLOCK 和 READUNCOMMITTED。

view_name

视图的名称及可选的别名。通过 view_name 来引用的视图必须是可更新的。由 INSERT 语句所做的修改不能影响视图的 FROM 子句中引用的多个基表。例如，在多表视图中的 INSERT 必须使用 column_list，column_list 是只引用来自一个基表的列。有关可更新视图的更多信息，请参见 CREATE VIEW。

rowset_function_limited

是 OPENQUERY 或 OPENROWSET 函数。

(column_list)

要在其中插入数据的一列或多列的列表。必须用圆括号将 column_list 括起来，并且用逗号进行分隔。

如果某列不在 column_list 中，则 Microsoft® SQL Server™ 必须能够基于该列的定义提供一个值；否则不能装载行。如果列满足下面的条件，那么 SQL Server 将自动为列提供值：

具有 IDENTITY 属性。使用下一个增量标识值。

有默认值。使用列的默认值。

具有 timestamp 数据类型。使用当前的时间戳值。

是可空的。使用空值。

当向标识列中插入显式的值时，必须使用 column_list 及 VALUES 列表，并且对于表，SET IDENTITY_INSERT 选项必须是 ON。

VALUES

引入要插入的数据值的列表。对于 column_list（如果已指定）中或者表中的每个列，都必须有一个数据值。必须用圆括号将值列表括起来。

如果 VALUES 列表中的值与表中列的顺序不相同，或者未包含表中所有列的值，那么必须使用 column_list 明确地指定存储每个传入值的列。

DEFAULT

强制 SQL Server 装载为列定义的默认值。如果对于某列并不存在默认值，并且该列允许 NULL，那么就插入 NULL。对于使用 timestamp 数据类型定义的列，插入下一个时间戳值。DEFAULT 对标识列无效。

expression

一个常量、变量或表达式。表达式不能包含 SELECT 或 EXECUTE 语句。

derived_table

任何有效的 SELECT 语句，它返回将装载到表中的数据行。

execute_statement

任何有效的 EXECUTE 语句，它使用 SELECT 或 READTEXT 语句返回数据。

如果将 execute_statement 与 INSERT 一起使用，那么每个结果集都必须与表中或 column_list 中的列兼容。execute_statement 可以用来执行同一服务器或远程服务器上的存储过程。执行远程服务器中的过程，然后将结果集返回到本地服务器，并装载到本地服务器的表中。如果 execute_statement 使用 READTEXT 语句返回数据，那么每个单独的 READTEXT 语句最多可以返回 1 MB (1024 KB) 的数据，也可以将 execute_statement 与扩展过程一起使用，并且插入扩展过程的主线程返回的数据。不会插入不是主线程的其它线程中的输出结果。

说明 对于 SQL Server 7.0，execute_statement 不包含返回 text 或 image 列的扩展存储过程。这个行为是从 SQL Server 早期版本变化而来的。

DEFAULT VALUES

强制新行包含为每个列所定义的默认值。

INSERT 将新行追加到表中。若要替换表中的数据，必须在使用 INSERT 装载新数据之前，使用 DELETE 或 TRUNCATE TABLE 语句清除现有的数据。若要修改现有行中的列值，请使用 UPDATE。若要创建新表，并且通过一个步骤给它装载数据，请使用 SELECT 语句的 INTO 选项。

table 变量在其作用域内可以像常规表一样访问。因此，可以像在 INSERT 语句中将行添加到表一样使用 table 变量。有关更多信息，请参见 table。

由 OPENDATASOURCE 函数建立的、作为服务器名部分的四段名称可以作为表源，该表源可以出现在 INSERT 语句中显示表名的所有位置。

使用 uniqueidentifier 数据类型创建的列存储特殊格式的 16 字节二进制值。与标识列不同，SQL Server 不会为带有 uniqueidentifier 数据类型的列自动地生成值。在插入操作过程中，带有 uniqueidentifier 数据类型的变量以及某些字符串常量可以用于 uniqueidentifier 列（这些字符串常量的形式为：xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx，有 36 个字符，其中包括连字符。x 是十六进制数，范围为 0-9 或 a-f。）。例如，对于 uniqueidentifier 变量或列，6F9619FF-8B86-D011-B42D-00C04FC964FF 是一个有效值。使用 NEWID() 函数可以获取全局唯一的 ID (GUID)。

插入行时，可以应用下列规则：

如果将值装载到带有 char、varchar 或 varbinary 数据类型的列，尾随空格（对于 char 和 varchar 是空格，对于 varbinary 是零）的填充和截断是由 SET ANSI_PADDING 设置确定的。该设置是在创建表时为列定义的。

下表显示 SET ANSI_PADDING 为 OFF 时的默认操作。

数据类型 | 默认操作
Char | 将带有空格的值填充到已定义的列宽。
Varchar | 删除最后的非空格字符后面的尾随空格，而对于只由空格组成的字符串，一直删除到只留下一个空格字符。
Varbinary | 删除尾随的零。

如果将一个空字符串 (' ') 装载到带有 varchar 或 text 数据类型的列，那么默认操作是装载一个零长度的字符串。如果数据库的兼容级别小于 70，那么将该值转换成单个空格。有关更多信息，请参见 sp_dbcmptlevel。

如果 INSERT 语句违反约束或规则，或者它有与列的数据类型不兼容的值，那么该语句就会失败，并且 SQL Server 显示错误信息。

将空值插入到 text 或 image 列不能创建有效的文本指针，也不能预分配 8 KB 的文本页。

如果 INSERT 正在使用 SELECT 或 EXECUTE 装载多行，正在装载的值中出现任何违反规则或约束的行为都会导致整个语句终止，从而不会装载任何行。

当向远程 SQL Server 表中插入值且没有为所有列指定值时，则用户必须标识将向其中插入指定值的列。

在本地和远程分区视图上，忽略 INSERT 语句的 SET ROWCOUNT 选项的设置。而且，当兼容级别设置为 80 时，在 SQL Server 2000 中的远程表上也不支持 INSERT 语句的 SET ROWCOUNT 选项。

当为表或视图的 INSERT 操作定义了 INSTEAD-OF 触发器时，该触发器就会执行 INSERT 语句中的 instead of。以前的 SQL Server 版本只支持在 INSERT 中定义的 AFTER 触发器，以及其它数据修改语句。

如果在表达式赋值过程中 INSERT 语句遇到算术错误（溢出、被零除或域错误），那么 SQL Server 会处理这些错误，就好像 SET ARITHABORT 是 ON 一样。批处理的其余部分将终止，并且会返回一条错误信息。

权限

默认情况下，INSERT 权限被授予 sysadmin 固定服务器角色成员，db_owner 和 db_datawriter 固定数据库角色成员，以及表的所有者。sysadmin、db_owner 和 db_securityadmin 角色成员和表所有者可以将权限转让给其他用户。

插入行的规则

插入行时，可以应用下列规则：

如果将值加载到 char、varchar 或 varbinary 数据类型的列中，则尾随空格（对于 char 和 varchar 为空格，对于 varbinary 为零）的填充或截断由创建表时为该列定义的 SET ANSI_PADDING 设置确定。

下表显示了 SET ANSI_PADDING OFF 的默认操作。

如果将一个空字符串 (' ') 加载到 varchar 或 text 数据类型的列，则默认操作是加载一个零长度的字符串。

如果 INSERT 语句违反约束或规则，或者包含与列的数据类型不兼容的值，则该语句将失败，并且数据库引擎显示错误消息。

将空值插入到 text 或 image 列不创建有效的文本指针，也不预分配 8 KB 的文本页。有关插入 text 和 image 数据的详细信息，请参阅使用 text、ntext 和 image 函数。

如果 INSERT 是使用 SELECT 或 EXECUTE 加载多行，那么一旦加载的值中出现任何违反规则或约束的情况，就会导致终止整个语句，且不会加载任何行。

当向远程数据库引擎实例的表中插入值且没有为所有列指定所有值时，用户必须标识将向其中插入指定值的列。

## 通过视图将数据装载到表

在下面的示例中，INSERT 语句指定一个视图名；但是将新行插入该视图的基础表中。INSERT 语句中 VALUES 列表的顺序必须与视图的列顺序相匹配。

1. IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

2. WHERE TABLE_NAME = 'T1')

3. DROP TABLE T1

4. GO

5. IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS

6. WHERE TABLE_NAME = 'V1')

7. DROP VIEW V1

8. GO

9. CREATE TABLE T1 ( column_1 int, column_2 varchar(30))

10. GO

11. CREATE VIEW V1 AS SELECT column_2, column_1

12. FROM T1

13. GO

14. INSERT INTO V1

15. VALUES ('Row 1',1)

16. SELECT *

17. FROM T1

## 使用 DEFAULT VALUES 选项装载数据

在下面的示例中，CREATE TABLE 语句给每个列定义一个值，当在 INSERT 语句中没有为列指定显式的值时，就可以使用这个值。使用 INSERT 语句的 DEFAULT VALUES 选项，无须提供显式的值就可以添加行。

1. IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

2. WHERE TABLE_NAME = 'T1')

3. DROP TABLE T1

4. GO

5. CREATE DEFAULT bound_default AS 'Bound default value'

6. GO

7. CREATE TABLE T1

8. ( column_1 int identity,

9. column_2 varchar(30)

10. CONSTRAINT default_name DEFAULT ('column default'),

11. column_3 timestamp,

12. column_4 varchar(30),

13. column_5 int NULL)

14. GO

15. USE master

16. EXEC sp_bindefault 'bound_default','T1.column_4'

17. INSERT INTO T1 DEFAULT VALUES

18. SELECT *

19. FROM T1

## 使用 SELECT 和 EXECUTE 选项装载数据

下面的示例演示三种不同的方法，用来从一个表获取数据，并将数据装载到另一个表。每种方法都基于一个多表 SELECT 语句，该语句在列列表中包含一个表达式及一个文字值。

第一个 INSERT 语句使用一个 SELECT 语句直接从源表 (authors) 检索数据，并且将结果集存储到 author_sales 表。第二个 INSERT 执行一个包含 SELECT 语句的过程，而第三个 INSERT 将 SELECT 语句作为一个文字字符串执行。

1. IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

2. WHERE TABLE_NAME = 'author_sales')

3. DROP TABLE author_sales

4. GO

5. IF EXISTS(SELECT name FROM sysobjects

6. WHERE name = 'get_author_sales' AND type = 'P')

7. DROP PROCEDURE get_author_sales

8. GO

9. USE pubs

10. CREATE TABLE author_sales

11. ( data_source varchar(20),

12. au_id varchar(11),

13. au_lname varchar(40),

14. sales_dollars smallmoney

15. )

16. GO

17. CREATE PROCEDURE get_author_sales

18. AS

19. SELECT 'PROCEDURE', authors.au_id, authors.au_lname,

20. SUM(titles.price * sales.qty)

21. FROM authors INNER JOIN titleauthor

22. ON authors.au_id = titleauthor.au_id INNER JOIN titles

23. ON titleauthor.title_id = titles.title_id INNER JOIN sales

24. ON titles.title_id = sales.title_id

25. WHERE authors.au_id like '8%'

26. GROUP BY authors.au_id, authors.au_lname

27. GO

28. --INSERT...SELECT example

29. USE pubs

30. INSERT author_sales

31. SELECT 'SELECT', authors.au_id, authors.au_lname,

32. SUM(titles.price * sales.qty)

33. FROM authors INNER JOIN titleauthor

34. ON authors.au_id = titleauthor.au_id INNER JOIN titles

35. ON titleauthor.title_id = titles.title_id INNER JOIN sales

36. ON titles.title_id = sales.title_id

37. WHERE authors.au_id LIKE '8%'

38. GROUP BY authors.au_id, authors.au_lname

39.

40. --INSERT...EXECUTE procedure example

41. INSERT author_sales EXECUTE get_author_sales

42.

43. --INSERT...EXECUTE('string') example

44. INSERT author_sales

45. EXECUTE

46. ('

47. SELECT ''EXEC STRING'', authors.au_id, authors.au_lname,

48. SUM(titles.price * sales.qty)

49. FROM authors INNER JOIN titleauthor

50. ON authors.au_id = titleauthor.au_id INNER JOIN titles

51. ON titleauthor.title_id = titles.title_id INNER JOIN sales

52. ON titles.title_id = sales.title_id

53. WHERE authors.au_id like ''8%''

54. GROUP BY authors.au_id, authors.au_lname

55. ')

56.

57. --Show results.

58. SELECT * FROM author_sales

## 使用 SELECT 语句中的 TOP 子句插入数据

因为可以在 INSERT 语句中指定 SELECT 语句，所以也可以将 TOP 子句用在 SELECT 语句中。下面的示例将 authors 表中最上面的 10 个作者插入到名为 new_authors 的新表中。

1. IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES

2. WHERE TABLE_NAME = 'new_authors')

3. DROP TABLE new_authors

4. GO

5. USE pubs

6. CREATE TABLE new_authors

7. (

8. au_id id,

9. au_lname varchar(40),

10. au_fname varchar(20),

11. phone char(12),

12. address varchar(40),

13. city varchar(20),

14. state char(2),

15. zip char(5),

16. contract bit

17. )

18. INSERT INTO new_authors

19. SELECT TOP 10 *

20. FROM authors

21.