You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在无连接条件下实现T-SQL记录的一对一匹配?

解决SQL中INSERT OUTPUT无法获取源表列及一对一配对的问题

你的问题核心在于INSERT语句的OUTPUT子句只能访问插入后生成的inserted对象列,无法直接引用SELECT子句里的源表列,所以没法直接把cba.Id和新生成的GlobalId一起存入临时表。另外,你之前用CROSS JOIN和ROW_NUMBER没成功,是因为没建立正确的关联关系,导致无法一对一配对。

正确的解决方案:使用MERGE语句代替INSERT

MERGE语句的优势在于,它能同时访问**源表(SOURCE)和目标插入的表(INSERTED)**的列,完美解决你需要同时获取新生成Id和源表Id的需求。下面是修改后的完整代码:

DECLARE @SignatureGlobalIdsTbl table (ID int, CompanyBankAccountId int);

-- 用MERGE代替INSERT,实现同时获取新GlobalId和源表的CompanyBankAccountId
MERGE INTO GlobalIds AS Target
USING (
    SELECT cba.CompanyBankAccountId, @DocumentsGlobalTypeKey AS TypeId
    FROM CompanyBankAccounts cba
    INNER JOIN Companies c ON c.CompanyId = cba.CompanyId
    WHERE SignatureDocumentId IS NULL AND (SignatureFile IS NOT NULL AND SignatureFile != '')
) AS Source (CompanyBankAccountId, TypeId)
ON 1 = 0 -- 永远不匹配,确保所有源行都被插入
WHEN NOT MATCHED THEN
    INSERT (TypeId) VALUES (Source.TypeId)
OUTPUT Inserted.Id, Source.CompanyBankAccountId INTO @SignatureGlobalIdsTbl (ID, CompanyBankAccountId);

-- 现在可以通过CompanyBankAccountId关联临时表,一对一获取对应的GlobalId
INSERT INTO Documents (DocumentPath, DocumentType, DocumentIsExternal, OwnerGlobalId, OwnerGlobalTypeID, DocumentName, Extension, GlobalId)
SELECT 
    cba.SignatureFile, 
    @SignatureDocumentTypeKey, 
    1, 
    c.GlobalId AS CompanyGlobalId, 
    @OwnerGlobalTypeKey, 
    [dbo].[fnGetFileNameWithoutExtension](cba.SignatureFile), 
    [dbo].[fnGetFileExtension](cba.SignatureFile), 
    s.ID AS documentGlobalId
FROM CompanyBankAccounts cba
INNER JOIN Companies c ON c.CompanyId = cba.CompanyId
INNER JOIN @SignatureGlobalIdsTbl s ON s.CompanyBankAccountId = cba.CompanyBankAccountId
WHERE cba.SignatureDocumentId IS NULL AND (cba.SignatureFile IS NOT NULL AND cba.SignatureFile != '');

关键说明:

  1. MERGE的关联条件:ON 1 = 0确保源表的每一行都不会和目标表(GlobalIds)匹配,所以所有源行都会执行INSERT操作,和你原来的INSERT逻辑一致。
  2. OUTPUT子句:这里可以同时获取Inserted.Id(新生成的GlobalId)和Source.CompanyBankAccountId(源表的银行账户Id),存入临时表后就建立了一对一的映射关系。
  3. 后续关联:插入Documents时,直接用CompanyBankAccountId关联临时表,避免了笛卡尔积,保证每一行源数据对应唯一的新GlobalId。

如果你坚持想用ROW_NUMBER的方法,也可以给源表和插入的GlobalIds都生成行号,然后通过行号关联,但MERGE的方法更简洁高效,是这类场景的标准解决方案。

内容的提问来源于stack exchange,提问作者johnny 5

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 08:32:36