插入数据

已完成

Transact-SQL 提供多种在表中插入行的方法。

INSERT 语句

INSERT 语句用于向表中添加一行或多行。 语句的形式有数种。

简单 INSERT 语句的基本语法如下所示:

INSERT [INTO] <Table> [(column_list)]
VALUES ([ColumnName or an expression or DEFAULT or NULL],…n)

利用这种形式的 INSERT 语句(称为“插入值”),可以指定将在其中放置值的列以及为插入表中的每一行显示数据的顺序。 column_list 是可选的,但建议使用。 在没有 column_list 的情况下,INSERT 语句对表中的每一列都期望一个值,顺序与定义列的顺序相同。 还可以作为逗号分隔列表来提供这些列的值。

列出值时,关键字 DEFAULT 表示将使用某个预定义值(表创建表时指定)。 可通过三种方式确定默认值:

  • 如果列已定义为具有自动生成的值,则将使用该值。 本模块后续部分中将讨论自动生成值。
  • 创建表时,可以为列提供默认值,如果指定了 DEFAULT,则使用该默认值。
  • 如果列已定义为允许 NULL 值,并且该列不是自动生成的列,且没有定义默认值,则 NULL 将作为 DEFAULT 插入。

表创建的细节超出了本模块的范围。 但是,查看表中有哪些列通常很有用。 最简单的方法就是对表执行 SELECT 语句,而不返回任何行。 通过使用永远不会返回 TRUE 值的 WHERE 条件,不能返回任何行。

SELECT * FROM Sales.Promotion
WHERE 1 = 0;

此语句将显示所有列及其名称,但不会显示数据类型或任何属性,例如是否允许 NULL 值,或者是否指定了默认值。 查询输出的示例可能如下所示:

PromotionName

StartDate

ProductModelID

折扣

说明

要向该表中插入数据,可以使用如下所示的 INSERT 语句。

INSERT INTO Sales.Promotion (PromotionName,StartDate,ProductModelID,Discount,Notes)
VALUES
('Clearance Sale', '01/01/2021', 23, 0.1, '10% discount');

对于上面的示例,可以省略列清单,因为我们按正确的顺序为每列提供一个值:

INSERT INTO Sales.Promotion
VALUES
('Clearance Sale', '01/01/2021', 23, 0.1, '10% discount');

假设表定义为:当前日期的默认值应用于 StartDate 列,并且 Notes 列允许 NULL 值。 可以明确指示想要使用这些值,如下所示:

INSERT INTO Sales.Promotion
VALUES
('Pull your socks up', DEFAULT, 24, 0.25, NULL);

或者,可以省略 INSERT 语句中的值,如果省略,则使用默认值(如果已定义),如果没有默认值,但列允许 NULL 值,则将插入 NULL。 如果没有为所有列提供值,则必须包含列清单,指出为哪些列提供了值。

INSERT INTO Sales.Promotion (PromotionName, ProductModelID, Discount)
VALUES
('Caps Locked', 2, 0.2);

INSERT VALUES 语句除了能够一次插入一行之外,还可用于插入多行,方法是提供多个逗号分隔的值集。 值集也用逗号分隔,如下所示:

(col1_val,col2_val,col3_val),
(col1_val,col2_val,col3_val)

这一值列表称为表值构造函数。 下面的示例使用表值构造函数将另外两行插入表中:

INSERT INTO Sales.Promotion
VALUES
('The gloves are off!', DEFAULT, 3, 0.25, NULL),
('The gloves are off!', DEFAULT, 4, 0.25, NULL);

INSERT ... SELECT

除了在 INSERT 语句中指定一组文本值以外,T-SQL 还支持使用其他运算的结果来提供 INSERT 的值。 可以使用 SELECT 语句的结果或存储过程的输出来提供 INSERT 语句的值。

要将 INSERT 与嵌套 SELECT 一起使用,请生成一个 SELECT 语句来替换 VALUES 子句。 通过这种格式(称为 INSERT SELECT),可将 SELECT 查询返回的行集插入到目标表中。 使用 INSERT SELECT 时,将显示与 INSERT VALUES 相同的注意事项:

  • 可以选择在表名称后面指定列清单。
  • 必须为每个列提供列值或默认值,或者提供 DEFAULT 或 NULL。

以下语法说明了 INSERT SELECT 的用法:

INSERT [INTO] <table or view> [(column_list)]
SELECT <column_list> FROM <table_list>...;

注意

也可以将来自存储过程(甚至动态批处理)的结果集用作 INSERT 语句的输入。 这种格式的 INSERT(称为 INSERT EXEC)在概念上类似于 INSERT SELECT,并且将显示相同的注意事项。 但是,存储过程可能会返回多个结果集,因此需要格外小心。

以下示例将为名为 Get Framed 的新促销插入多行,方法是:从 Production.ProductModel(这是一个表,列出了名称中包含“frame”的所有模型)中检索模型 ID 和模型名称。

INSERT INTO Sales.Promotion (PromotionName, ProductModelID, Discount, Notes)
SELECT DISTINCT 'Get Framed', m.ProductModelID, 0.1, '10% off ' + m.Name
FROM Production.ProductModel AS m
WHERE m.Name LIKE '%frame%';

与子查询不同,与 INSERT 一起使用的嵌套 SELECT 不用括号括起。

SELECT ... INTO

插入行的另一种选择是 SELECT INTO 语句,该语句与 INSERT SELECT 语句类似。 INSERT SELECT 和 SELECT INTO 的最大区别在于,SELECT INTO 不能用于将行插入到现有表中,因为 SELECT INTO 始终会根据 SELECT 的结果创建一个新表。 新表中的每列的名称、数据类型、为 null 性均与 SELECT 列表中对应的列(或表达式)相同。

要使用 SELECT INTO,请在查询的 SELECT 子句中添加 <>(就在 FROM 子句前面)。 下面的示例将 Sales.SalesOrderHeader 表中的数据提取到名为 Sales.Invoice 的新表中。

SELECT SalesOrderID, CustomerID, OrderDate, PurchaseOrderNumber, TotalDue
INTO Sales.Invoice
FROM Sales.SalesOrderHeader;

如果已经存在一个表名与 INTO 后面指定的名称相同,则 SELECT INTO 将失败。 创建表后,可以像处理任何其他表一样处理该表。 可以选择这个表,将其联接到其他表,或在表中插入更多行。