INSERT INTO Cities (Location)
VALUES ( dbo.CreateNewPoint(x, y) );
Error Handling
可以通过在 TRY…CATCH 构造函数中指定 INSERT 语句,实现对该语句的错误处理。
如果 INSERT 语句违反约束或规则,或者包含与列的数据类型不兼容的值,则该语句将失败,并且返回错误消息。
如果 INSERT 是使用 SELECT 或 EXECUTE 加载多行,那么一旦加载的值中出现任何违反规则或约束的情况,就会导致终止语句,且不会加载任何行。
如果在表达式计算过程中 INSERT 语句遇到算术错误(溢出、被零除或域错误),则数据库引擎会处理这些错误,就好像 SET ARITHABORT 设置为 ON 一样。 停止批处理,并返回一条错误消息。 如果 SET ARITHABORT 和 SET ANSI_WARNINGS 为 OFF,并且在对表达式求值的过程中 INSERT、DELETE 或 UPDATE 语句遇到算术错误(溢出、被零除或域错误),SQL Server 将插入或更新一个 NULL 值。 如果目标列不可为空,则插入或更新操作将失败,用户将收到错误消息。
Interoperability
当为表或视图的 INSERT 操作定义了 INSTEAD OF
触发器时,则执行该触发器而不是 INSERT 语句。 有关 INSTEAD OF
触发器的详细信息,请参阅 CREATE TRIGGER (Transact-SQL)。
限制和局限
当向远程表中插入值且没有为所有列指定所有值时,用户必须标识将向其中插入指定值的列。
在将 TOP 与 INSERT 结合使用时,被引用行不按任何顺序排列,不能直接在此语句中指定 ORDER BY 子句。 如果需要使用 TOP 来插入按有意义的时间顺序排列的行,您必须同时使用 TOP 和在嵌套 select 语句中指定的 ORDER BY 子句。 请参阅本主题后面的“示例”一节。
使用 SELECT 和 ORDER BY 填充行的 INSERT 查询保证了标识值的计算方式,但不能保证行的插入顺序。
在并行数据仓库中,除非另外还指定了 TOP,否则 ORDER BY 子句在 VIEWS、CREATE TABLE AS SELECT、INSERT SELECT、内联函数、派生表、子查询和常见表表达式中无效。
Logging Behavior
INSERT 语句始终完全记入日志,只有在将 OPENROWSET 函数与 BULK 关键字一起使用或者在使用 INSERT INTO <target_table> SELECT <columns> FROM <source_table>
时除外。 这些操作可进行最小日志记录。 有关详细信息,请参阅本主题前面的“大容量加载数据的最佳做法”一节。
在链接服务器的连接过程中,发送服务器提供登录名和密码以代表自己连接到接收服务器。 为了使该连接有效,必须使用 sp_addlinkedsrvlogin 在链接服务器之间创建登录名映射。
使用 OPENROWSET(BULK…) 时,请务必了解 SQL Server 是如何处理模拟的。 有关详细信息,请参阅使用 BULK INSERT 或 OPENROWSET(BULK...) 批量导入数据 (SQL Server) 中的“安全注意事项”。
Permissions
需要对目标表具有 INSERT 权限。
INSERT 权限默认授予 sysadmin
固定服务器角色、db_owner
和 db_datawriter
固定数据库角色以及表所有者的成员。
sysadmin
、db_owner
和 db_securityadmin
角色以及表所有者的成员可以将权限转让给其他用户。
若要使用 OPENROWSET 函数 BULK 选项执行 INSERT,你必须是 sysadmin
固定服务器角色成员或 bulkadmin
固定服务器角色成员。
Examples
Category
作为特征的语法元素
本节中的示例说明了使用最低要求的语法的 INSERT 语句的基本功能。
A. 插入单行数据
下面的示例在 AdventureWorks2022 数据库的 Production.UnitMeasure
表中插入一行。 该表中的各列是 UnitMeasureCode
、Name
和 ModifiedDate
。 由于提供了所有列的值并按表中各列的顺序列出这些值,因此不必在列列表中指定列名**。
INSERT INTO Production.UnitMeasure
VALUES (N'FT', N'Feet', '20080414');
B. 插入多行数据
下面的示例使用表值构造函数在单个 INSERT 语句中将三行插入 AdventureWorks2022 数据库的 Production.UnitMeasure
表。 由于提供了所有列的值并按表中各列的顺序列出这些值,因此不必在列列表中指定列名。
Azure Synapse Analytics 不支持表值构造函数。
INSERT INTO Production.UnitMeasure
VALUES (N'FT2', N'Square Feet ', '20080923'), (N'Y', N'Yards', '20080923')
, (N'Y3', N'Cubic Yards', '20080923');
C. 按与表列顺序不同的顺序插入数据
下面的示例使用列列表显式指定插入到每个列中的值。 AdventureWorks2022 数据库的 Production.UnitMeasure
表中的列顺序为 UnitMeasureCode
、Name
、ModifiedDate
;但这些列的列出顺序与 column_list 中的顺序不同。
INSERT INTO Production.UnitMeasure (Name, UnitMeasureCode,
ModifiedDate)
VALUES (N'Square Yards', N'Y2', GETDATE());
本节中的示例演示了向使用 IDENTITY 属性、DEFAULT 值定义的列中插入值的方法,或者使用数据类型(如 uniqueidentifier 或用户定义的类型列)进行定义。
D. 将数据插入其列具有默认值的表
下面的示例演示了如何将行插入到包含自动生成值或具有默认值的列的表中。
Column_1
是一个计算列,它通过将一个字符串与插入 column_2
的值进行串联,自动生成一个值。
Column_2
是用默认约束定义的。 如果没有为该列指定值,将使用默认值。
Column_3
是使用 rowversion 数据类型定义的,它自动生成一个唯一的、递增的二进制数字。
Column_4
不自动生成值。 如果没有为该列指定值,将插入 NULL。 INSERT 语句插入一些行,这些行只有部分列包含值。 在最后一个 INSERT 语句中,未指定列,只通过使用 DEFAULT VALUES 子句插入了默认值。
CREATE TABLE dbo.T1
column_1 AS 'Computed column ' + column_2,
column_2 varchar(30)
CONSTRAINT default_name DEFAULT ('my column default'),
column_3 rowversion,
column_4 varchar(40) NULL
INSERT INTO dbo.T1 (column_4)
VALUES ('Explicit value');
INSERT INTO dbo.T1 (column_2, column_4)
VALUES ('Explicit value', 'Explicit value');
INSERT INTO dbo.T1 (column_2)
VALUES ('Explicit value');
INSERT INTO T1 DEFAULT VALUES;
SELECT column_1, column_2, column_3, column_4
FROM dbo.T1;
E. 将数据插入到含标识列的表中
下面的示例演示了将数据插入到标识列中的不同方法。 前两个 INSERT 语句允许为新行生成标识值。 第三个 INSERT 语句用 SET IDENTITY_INSERT 语句覆盖列的 IDENTITY 属性,并将一个显式值插入到标识列中。
CREATE TABLE dbo.T1 ( column_1 int IDENTITY, column_2 VARCHAR(30));
INSERT T1 VALUES ('Row #1');
INSERT T1 (column_2) VALUES ('Row #2');
SET IDENTITY_INSERT T1 ON;
INSERT INTO T1 (column_1,column_2)
VALUES (-99, 'Explicit identity value');
SELECT column_1, column_2
FROM T1;
F. 通过使用 NEWID() 将数据插入到 uniqueidentifier 列中
下面的示例使用 NEWID() 函数获取 column_2
的 GUID。 与标识列不同,数据库引擎 不为 uniqueidentifier 数据类型的列自动生成值(如第二个 INSERT
语句所示)。
CREATE TABLE dbo.T1
column_1 int IDENTITY,
column_2 uniqueidentifier,
INSERT INTO dbo.T1 (column_2)
VALUES (NEWID());
INSERT INTO T1 DEFAULT VALUES;
SELECT column_1, column_2
FROM dbo.T1;
G. 将数据插入到用户定义类型列中
下面的 Transact-SQL 语句将三行插入到 PointValue
表的 Points
列中。 该列使用 CLR 用户定义类型 (UDT)。
Point
数据类型由作为 UDT 属性公开的 X 和 Y 整数值组成。 必须使用 CAST 或 CONVERT 函数,才能将以逗号分隔的 X 和 Y 值转换为 Point
类型。 前两个语句使用 CONVERT 函数将字符串值转换为 Point
类型,第三个语句使用 CAST 函数。 有关详细信息,请参阅操作 UDT 数据。
INSERT INTO dbo.Points (PointValue) VALUES (CONVERT(Point, '3,4'));
INSERT INTO dbo.Points (PointValue) VALUES (CONVERT(Point, '1,5'));
INSERT INTO dbo.Points (PointValue) VALUES (CAST ('1,99' AS Point));
插入来自其他表的数据
本节中的示例说明将行从一个表插入另一个表的方法。
H. 使用 SELECT 和 EXECUTE 选项插入来自其他表的数据
下面的示例说明如何使用 INSERT…SELECT 或 INSERT…EXECUTE 将来自一个表的数据插入另一个表。 每种方法都基于一个多表 SELECT 语句,该语句在列列表中包含一个表达式及一个文字值。
第一个 INSERT 语句使用 SELECT 语句从 AdventureWorks2022 数据库的源表(Employee
、SalesPerson
和 Person
)中派生数据,并将结果集存储在 EmployeeSales
表中。 第二个 INSERT 语句使用 EXECUTE 子句调用包含 SELECT 语句的存储过程,第三个 INSERT 使用 EXECUTE 子句将 SELECT 语句作为文字字符串引用。
CREATE TABLE dbo.EmployeeSales
( DataSource varchar(20) NOT NULL,
BusinessEntityID varchar(11) NOT NULL,
LastName varchar(40) NOT NULL,
SalesDollars money NOT NULL
CREATE PROCEDURE dbo.uspGetEmployeeSales
SET NOCOUNT ON;
SELECT 'PROCEDURE', sp.BusinessEntityID, c.LastName,
sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE '2%'
ORDER BY sp.BusinessEntityID, c.LastName;
--INSERT...SELECT example
INSERT INTO dbo.EmployeeSales
SELECT 'SELECT', sp.BusinessEntityID, c.LastName, sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE '2%'
ORDER BY sp.BusinessEntityID, c.LastName;
--INSERT...EXECUTE procedure example
INSERT INTO dbo.EmployeeSales
EXECUTE dbo.uspGetEmployeeSales;
--INSERT...EXECUTE('string') example
INSERT INTO dbo.EmployeeSales
EXECUTE
SELECT ''EXEC STRING'', sp.BusinessEntityID, c.LastName,
sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE ''2%''
ORDER BY sp.BusinessEntityID, c.LastName
--Show results.
SELECT DataSource,BusinessEntityID,LastName,SalesDollars
FROM dbo.EmployeeSales;
I. 使用 WITH 公共表表达式定义插入的数据
以下示例在 AdventureWorks2022 数据库中创建 NewEmployee
表。 公用表表达式 (EmployeeTemp
) 定义要插入到 NewEmployee
表中的来自一个或多个表的行。 INSERT 语句引用公用表表达式中的列。
CREATE TABLE HumanResources.NewEmployee
EmployeeID int NOT NULL,
LastName nvarchar(50) NOT NULL,
FirstName nvarchar(50) NOT NULL,
PhoneNumber Phone NULL,
AddressLine1 nvarchar(60) NOT NULL,
City nvarchar(30) NOT NULL,
State nchar(3) NOT NULL,
PostalCode nvarchar(15) NOT NULL,
CurrentFlag Flag
WITH EmployeeTemp (EmpID, LastName, FirstName, Phone,
Address, City, StateProvince,
PostalCode, CurrentFlag)
AS (SELECT
e.BusinessEntityID, c.LastName, c.FirstName, pp.PhoneNumber,
a.AddressLine1, a.City, sp.StateProvinceCode,
a.PostalCode, e.CurrentFlag
FROM HumanResources.Employee e
INNER JOIN Person.BusinessEntityAddress AS bea
ON e.BusinessEntityID = bea.BusinessEntityID
INNER JOIN Person.Address AS a
ON bea.AddressID = a.AddressID
INNER JOIN Person.PersonPhone AS pp
ON e.BusinessEntityID = pp.BusinessEntityID
INNER JOIN Person.StateProvince AS sp
ON a.StateProvinceID = sp.StateProvinceID
INNER JOIN Person.Person as c
ON e.BusinessEntityID = c.BusinessEntityID
INSERT INTO HumanResources.NewEmployee
SELECT EmpID, LastName, FirstName, Phone,
Address, City, StateProvince, PostalCode, CurrentFlag
FROM EmployeeTemp;
J. 使用 TOP 限制从源表插入的数据
下面的示例创建 EmployeeSales
表,并插入 AdventureWorks2022 数据库的 HumanResources.Employee
表中的前 5 名随机雇员的姓名和本年度到目前为止的销售数据。 INSERT 语句选择 SELECT
语句返回的任意 5 行。 OUTPUT 子句将显示插入 EmployeeSales
表中的行。 请注意,SELECT 语句中的 ORDER BY 子句不用于确定前 5 名雇员。
CREATE TABLE dbo.EmployeeSales
( EmployeeID nvarchar(11) NOT NULL,
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
YearlySales money NOT NULL
INSERT TOP(5)INTO dbo.EmployeeSales
OUTPUT inserted.EmployeeID, inserted.FirstName,
inserted.LastName, inserted.YearlySales
SELECT sp.BusinessEntityID, c.LastName, c.FirstName, sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.SalesYTD > 250000.00
ORDER BY sp.SalesYTD DESC;
如果必须使用 TOP 来插入按有意义的时间顺序排列的行,您必须同时使用 TOP 和嵌套 select 语句中的 ORDER BY,如以下示例所示。 OUTPUT 子句将显示插入 EmployeeSales
表中的行。 请注意,现在基于 ORDER BY 子句的结果而非随机行插入前 5 名员工。
INSERT INTO dbo.EmployeeSales
OUTPUT inserted.EmployeeID, inserted.FirstName,
inserted.LastName, inserted.YearlySales
SELECT TOP (5) sp.BusinessEntityID, c.LastName, c.FirstName, sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.SalesYTD > 250000.00
ORDER BY sp.SalesYTD DESC;
指定目标对象,而非标准表
本节中的示例说明如何通过指定视图或表变量来插入行。
K. 通过指定视图来插入数据
下面的示例将一个视图名指定为目标对象,但将新行插入到基础基表中。
INSERT
语句中值的顺序必须与视图的列顺序相匹配。 有关详细信息,请参阅通过视图修改数据。
CREATE TABLE T1 ( column_1 int, column_2 varchar(30));
CREATE VIEW V1 AS
SELECT column_2, column_1
FROM T1;
INSERT INTO V1
VALUES ('Row 1',1);
SELECT column_1, column_2
FROM T1;
SELECT column_1, column_2
FROM V1;
L. 向表变量中插入数据
下面的示例将一个表变量指定为 AdventureWorks2022 数据库中的目标对象。
-- Create the table variable.
DECLARE @MyTableVar table(
LocationID int NOT NULL,
CostRate smallmoney NOT NULL,
NewCostRate AS CostRate * 1.5,
ModifiedDate datetime);
-- Insert values into the table variable.
INSERT INTO @MyTableVar (LocationID, CostRate, ModifiedDate)
SELECT LocationID, CostRate, GETDATE()
FROM Production.Location
WHERE CostRate > 0;
-- View the table variable result set.
SELECT * FROM @MyTableVar;
向远程表中插入行
本节中的示例说明如何通过使用链接服务器或行集函数引用一个远程目标表,向该表插入行。
M. 通过使用链接服务器向远程表插入数据
下面的示例将行插入一个远程表中。 该示例从使用 sp_addlinkedserver 创建指向远程数据源的链接开始。 然后,将链接服务器名称 MyLinkServer
指定为 server.catalog.schema.object 形式的由四个部分组成的对象名称的一部分。
适用于:SQL Server 2008 (10.0.x) 及更高版本。
USE master;
-- Create a link to the remote data source.
-- Specify a valid server name for @datasrc as 'server_name'
-- or 'server_nameinstance_name'.
EXEC sp_addlinkedserver @server = N'MyLinkServer',
@srvproduct = N' ',
@provider = N'SQLNCLI',
@datasrc = N'server_name',
@catalog = N'AdventureWorks2022';
-- Specify the remote data source in the FROM clause using a four-part name
-- in the form linked_server.catalog.schema.object.
INSERT INTO MyLinkServer.AdventureWorks2022.HumanResources.Department (Name, GroupName)
VALUES (N'Public Relations', N'Executive General and Administration');
N. 通过使用 OPENQUERY 函数向远程表插入数据
下面的示例通过指定 OPENQUERY 行集函数向远程表插入一行。 在之前例子中创建的链接服务器名称用于此示例。
适用于:SQL Server 2008 (10.0.x) 及更高版本。
INSERT OPENQUERY (MyLinkServer,
'SELECT Name, GroupName
FROM AdventureWorks2022.HumanResources.Department')
VALUES ('Environmental Impact', 'Engineering');
O. 通过使用 OPENDATASOURCE 函数向远程表插入数据
下面的示例通过指定 OPENDATASOURCE 行集函数向远程表插入一行。 通过使用 server_name 或 server_name\instance_name 格式,为该数据源指定一个有效的服务器名称 。
适用于:SQL Server 2008 (10.0.x) 及更高版本。
-- Use the OPENDATASOURCE function to specify the remote data source.
-- Specify a valid server name for Data Source using the format
-- server_name or server_nameinstance_name.
INSERT INTO OPENDATASOURCE('SQLNCLI',
'Data Source= <server_name>; Integrated Security=SSPI')
.AdventureWorks2022.HumanResources.Department (Name, GroupName)
VALUES (N'Standards and Methods', 'Quality Assurance');
P. 插入到使用 PolyBase 创建的外部表中
将数据从 SQL Server 导出到 Hadoop 或 Azure 存储空间。 首先,创建一个指向目标文件或目录的外部表。 然后,使用 INSERT INTO 将数据从本地 SQL Server 表导出到外部数据源。 INSERT INTO 语句将创建目标文件或目录(如果不存在),而 SELECT 语句的结果将以指定文件格式导出到指定位置。 有关详细信息,请参阅 PolyBase 入门。
适用于: SQL Server。
-- Create an external table.
CREATE EXTERNAL TABLE [dbo].[FastCustomers2009] (
[FirstName] char(25) NOT NULL,
[LastName] char(25) NOT NULL,
[YearlyIncome] float NULL,
[MaritalStatus] char(1) NOT NULL
WITH (
LOCATION='/old_data/2009/customerdata.tbl',
DATA_SOURCE = HadoopHDP2,
FILE_FORMAT = TextFileFormat,
REJECT_TYPE = VALUE,
REJECT_VALUE = 0
-- Export data: Move old data to Hadoop while keeping
-- it query-able via external table.
INSERT INTO dbo.FastCustomer2009
SELECT T.* FROM Insured_Customers T1 JOIN CarSensor_Data T2
ON (T1.CustomerKey = T2.CustomerKey)
WHERE T2.YearMeasured = 2009 and T2.Speed > 40;
从表或数据字段中大容量加载数据
本节中的示例说明通过 INSERT 语句向表中大容量加载数据的两个方法。
Q. 将数据插入堆中并按最小方式记录日志
下面的示例创建一个新表(一个堆),并使用最小方式记录日志将来自其他表中的数据插入到这个新表中。 此示例假定 AdventureWorks2022
数据库的恢复模式设置为 FULL。 若要确保使用最小方式记录,应在插入行之前将 AdventureWorks2022
数据库的恢复模式设置为 BULK_LOGGED,并在 INSERT INTO…SELECT 语句后重置为 FULL。 此外,为目标表 Sales.SalesHistory
指定了 TABLOCK 提示。 这确保语句在事务日志中占用最少的空间并且高效执行。
-- Create the target heap.
CREATE TABLE Sales.SalesHistory(
SalesOrderID int NOT NULL,
SalesOrderDetailID int NOT NULL,
CarrierTrackingNumber nvarchar(25) NULL,
OrderQty smallint NOT NULL,
ProductID int NOT NULL,
SpecialOfferID int NOT NULL,
UnitPrice money NOT NULL,
UnitPriceDiscount money NOT NULL,
LineTotal money NOT NULL,
rowguid uniqueidentifier ROWGUIDCOL NOT NULL,
ModifiedDate datetime NOT NULL );
-- Temporarily set the recovery model to BULK_LOGGED.
ALTER DATABASE AdventureWorks2022
SET RECOVERY BULK_LOGGED;
-- Transfer data from Sales.SalesOrderDetail to Sales.SalesHistory
INSERT INTO Sales.SalesHistory WITH (TABLOCK)
(SalesOrderID,
SalesOrderDetailID,
CarrierTrackingNumber,
OrderQty,
ProductID,
SpecialOfferID,
UnitPrice,
UnitPriceDiscount,
LineTotal,
rowguid,
ModifiedDate)
SELECT * FROM Sales.SalesOrderDetail;
-- Reset the recovery model.
ALTER DATABASE AdventureWorks2022
SET RECOVERY FULL;
R. 将 OPENROWSET 函数与 BULK 一起使用来将数据大容量加载到表中
下面的示例通过指定 OPENROWSET 函数,将来自数据文件的行插入表中。 出于性能优化目的,指定了 IGNORE_TRIGGERS 表提示。 若要查看更多示例,请参阅使用 BULK INSERT 或 OPENROWSET(BULK...) 导入批量数据 (SQL Server)。
适用于:SQL Server 2008 (10.0.x) 及更高版本。
INSERT INTO HumanResources.Department WITH (IGNORE_TRIGGERS) (Name, GroupName)
SELECT b.Name, b.GroupName
FROM OPENROWSET (
BULK 'C:SQLFilesDepartmentData.txt',
FORMATFILE = 'C:SQLFilesBulkloadFormatFile.xml',
ROWS_PER_BATCH = 15000)AS b ;
通过使用提示覆盖查询优化器的默认行为
本节中的示例说明如何使用表提示在处理 INSERT 语句时暂时覆盖查询优化器的默认行为。
Caution
由于 SQL Server 查询优化器通常会为查询选择最佳执行计划,因此我们建议仅在最后迫不得已的情况下才可由资深的开发人员和数据库管理员使用提示。
S. 使用 TABLOCK 提示指定锁定方法
下面的示例指定对 Production.Location 表采用排他 (X) 锁,并保持到 INSERT 语句结束。
适用范围:SQL Server、SQL 数据库。
INSERT INTO Production.Location WITH (XLOCK)
(Name, CostRate, Availability)
VALUES ( N'Final Inventory', 15.00, 80.00);
捕获 INSERT 语句的结果
本节中的示例说明如何使用 OUTPUT Clause 从 INSERT 语句影响的每一行返回信息(或基于的表达式)。 这些结果可以返回到处理应用程序,以供在确认消息、存档以及其他类似的应用程序要求中使用。
T. 将 OUTPUT 用于 INSERT 语句
下面的示例将行插入到 ScrapReason
表中,并使用 OUTPUT
子句将语句的结果返回到 @MyTableVar
表变量。 由于 ScrapReasonID
列使用 IDENTITY
属性定义,因此未在 INSERT
语句中为该列指定值。 但应注意,数据库引擎为该列生成的值在 OUTPUT
列中的 INSERTED.ScrapReasonID
子句中返回。
DECLARE @MyTableVar table( NewScrapReasonID smallint,
Name varchar(50),
ModifiedDate datetime);
INSERT Production.ScrapReason
OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
INTO @MyTableVar
VALUES (N'Operator error', GETDATE());
--Display the result set of the table variable.
SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;
--Display the result set of the table.
SELECT ScrapReasonID, Name, ModifiedDate
FROM Production.ScrapReason;
U. 将 OUTPUT 用于标识列和计算列
下面的示例创建 EmployeeSales
表,然后使用 INSERT 语句向其中插入若干行,并使用 SELECT 语句从源表中检索数据。
EmployeeSales
表包含标识列 (EmployeeID
) 和计算列 (ProjectedSales
)。 由于这些值是在插入操作期间由数据库引擎生成的,因此不能在 @MyTableVar
中定义上述两列。
CREATE TABLE dbo.EmployeeSales
( EmployeeID int IDENTITY (1,5)NOT NULL,
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL,
ProjectedSales AS CurrentSales * 1.10
DECLARE @MyTableVar table(
LastName nvarchar(20) NOT NULL,
FirstName nvarchar(20) NOT NULL,
CurrentSales money NOT NULL
INSERT INTO dbo.EmployeeSales (LastName, FirstName, CurrentSales)
OUTPUT INSERTED.LastName,
INSERTED.FirstName,
INSERTED.CurrentSales
INTO @MyTableVar
SELECT c.LastName, c.FirstName, sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE '2%'
ORDER BY c.LastName, c.FirstName;
SELECT LastName, FirstName, CurrentSales
FROM @MyTableVar;
SELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSales
FROM dbo.EmployeeSales;
V. 插入从 OUTPUT 子句返回的数据
下面的示例捕获从 MERGE 语句的 OUTPUT 子句返回的数据,并将该数据插入到另一个表中。 MERGE 语句每天根据 AdventureWorks2022 数据库的 Quantity
表中处理的订单更新 ProductInventory
表的 SalesOrderDetail
列。 它还删除库存降为 0 的产品所在的行。 本示例捕获已删除的行并将这些行插入另一个表 ZeroInventory
中,该表跟踪没有库存的产品。
--Create ZeroInventory table.
CREATE TABLE Production.ZeroInventory (DeletedProductID int, RemovedOnDate DateTime);
INSERT INTO Production.ZeroInventory (DeletedProductID, RemovedOnDate)
SELECT ProductID, GETDATE()
( MERGE Production.ProductInventory AS pi
USING (SELECT ProductID, SUM(OrderQty) FROM Sales.SalesOrderDetail AS sod
JOIN Sales.SalesOrderHeader AS soh
ON sod.SalesOrderID = soh.SalesOrderID
AND soh.OrderDate = '20070401'
GROUP BY ProductID) AS src (ProductID, OrderQty)
ON (pi.ProductID = src.ProductID)
WHEN MATCHED AND pi.Quantity - src.OrderQty <= 0
THEN DELETE
WHEN MATCHED
THEN UPDATE SET pi.Quantity = pi.Quantity - src.OrderQty
OUTPUT $action, deleted.ProductID) AS Changes (Action, ProductID)
WHERE Action = 'DELETE';
IF @@ROWCOUNT = 0
PRINT 'Warning: No rows were inserted';
SELECT DeletedProductID, RemovedOnDate FROM Production.ZeroInventory;
W. 使用 SELECT 选项插入数据
以下示例说明如何使用 INSERT 语句通过 SELECT 选项插入多行数据。 第一个 INSERT
语句使用 SELECT
语句直接从源表中检索数据,然后将结果集存储在 EmployeeTitles
表中。
CREATE TABLE EmployeeTitles
( EmployeeKey INT NOT NULL,
LastName varchar(40) NOT NULL,
Title varchar(50) NOT NULL
INSERT INTO EmployeeTitles
SELECT EmployeeKey, LastName, Title
FROM ssawPDW.dbo.DimEmployee
WHERE EndDate IS NULL;
X. 使用 INSERT 语句指定标签
以下示例说明了如何通过 INSERT 语句使用标签。
-- Uses AdventureWorks
INSERT INTO DimCurrency
VALUES (500, N'C1', N'Currency1')
OPTION ( LABEL = N'label1' );
Y. 通过 INSERT 语句使用标签和查询提示
此查询显示通过 INSERT 语句使用标签和查询联接提示的基本语法。 将查询提交到控制节点后,运行在计算节点上的 SQL Server 将在生成 SQL Server 查询计划时应用哈希联接策略。 有关联接提示以及如何使用 OPTION 子句的详细信息,请参阅 OPTION (SQL Server PDW)。
-- Uses AdventureWorks
INSERT INTO DimCustomer (CustomerKey, CustomerAlternateKey,
FirstName, MiddleName, LastName )
SELECT ProspectiveBuyerKey, ProspectAlternateKey,
FirstName, MiddleName, LastName
FROM ProspectiveBuyer p JOIN DimGeography g ON p.PostalCode = g.PostalCode
WHERE g.CountryRegionCode = 'FR'
OPTION ( LABEL = 'Add French Prospects', HASH JOIN);
See Also
BULK INSERT (Transact-SQL)
DELETE (Transact-SQL)
EXECUTE (Transact-SQL)
FROM (Transact-SQL)
IDENTITY(属性)(Transact-SQL)
NEWID (Transact-SQL)
SELECT (Transact-SQL)
UPDATE (Transact-SQL)
MERGE (Transact-SQL)
OUTPUT 子句 (Transact-SQL)
使用插入的和删除的表