我有一个相对简单的问题,有一个隐含的答案,但不是一个明确的答案。这是背景。
以下是我正在使用的 3 个模式:
--Source Data:
ProjectID, ProjectName, CompanyName
--SQL Tables:
Project ( ProjectID [PK\Identity], ProjectName, CompanyID )
Company ( CompanyID [PK\Identity], CompanyName )
Project.CompanyID 是 Company.CompanyID 的外键。一切都很基本。
现在,因为我必须将源数据中的 CompanyName 转换为其规范化形式,所以插入是一个多步骤的过程。第一步是合并到公司:
MERGE INTO [Company] AS tgt
USING (SELECT CompanyName FROM [Source Data]) as src (CompanyName)
ON tgt.CompanyName = src.CompanyName
WHEN NOT MATCHED THEN
INSERT (CompanyName)
VALUES (src.CompanyName)
OUTPUT inserted.CompanyID
;
简而言之,如果 CompanyName 不在表中,则插入它,并输出标识值。足够明智,但实际上没有用,因为 OUTPUT 子句的结果没有排序。
这是我的方法:
MERGE INTO [Company] AS tgt
USING (SELECT ProjectID, CompanyName FROM [Source Data]) as src (ProjectID, CompanyName)
ON tgt.CompanyName = src.CompanyName
WHEN NOT MATCHED THEN
INSERT (CompanyName)
VALUES (src.CompanyName)
OUTPUT inserted.CompanyID, src.ProjectID
;
通过使用dml_select_list 中的from_table_name语法元素,我可以(理论上)在 ProjectID 和 CompanyID 之间建立直接关系,并在第二次插入到 Project 表中时使用该关系。
我的问题是——我真的可以信任这种关系吗?
该文档写得不好(https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-ver16):
列前缀,指定 DELETE、UPDATE 或 MERGE 语句的 FROM 子句中包含的表,该语句用于指定要更新或删除的行。
对于其中一个,我没有使用 FROM 子句,对于两个,我正在插入,而不是更新或删除。它实际上也没有描述列之间的关系。我可以假设或推断 insert.CompanyID 和 src.ProjectID 之间存在直接关联,因为如果没有这种关联,使用 from_table_name 的功能似乎毫无用处。
那么有人知道insert和from_table_name之间的底层连接的确切性质吗?
您可以相信
inserted.CompanyID
和src.ProjectID
值与相同的源行和目标行关联。来自文档:
换句话说,对于此
MERGE
子句,每个源行要么导致INSERT
操作,要么不导致操作。我认为这是您所追求的链接:插入的目标行恰好与一个源行相关联。源行是否与目标行匹配由子句确定
ON
。插入行时,引用的任何源行值都来自单个源行。生成的任何标识值都与插入的行相关联。两者之间的一对一关系完成了剩下的工作。不存在这样的连接。两者都是引用与每个受影响的行关联的值的方法。前缀
inserted
指定目标表行中的更改后值。前缀from_table_name
限定子句中的非目标属性FROM
(或者,在 a 的情况下MERGE
,USING
限定子句)。一般来说,
MERGE
可以防止多个源行导致对同一目标行执行操作。如果语句和模式不能保证这一点,则会将其他运算符添加到执行计划中以检测条件并在运行时发生错误时引发错误。一个例外是多个源行导致对同一目标行执行删除操作。在这种情况下,仅执行第一个操作;重复项将被丢弃。不允许对同一目标行进行多次更新或更新和删除的任意组合。
为了完整地描述这一情况,使用某些子句,单个源行可以影响多个目标行
MERGE
。在这种情况下,OUTPUT
可以从特定目标行的属性和源行(如果存在)构造数据。没有 的源行WHEN NOT MATCHED BY SOURCE
,因此在这种情况下不允许源列引用。有关更多详细信息,请参阅已停用文档中的使用 MERGE 插入、更新和删除数据。