使用多个 table 来源合并(用户定义 Table 类型和输入参数)

Merge using Multiple table sources (User Defined Table Type & Input Parameters)

我正在尝试将数据更新到一个名为“CustomOrderReqs”的 table 中。我将 insert/update 数据定期使用用户定义的 Table 类型和输入参数存储到此 table 中。我有最终的 table 如下:

CustomOrderReqs

我定义了一个用户定义的 Table 类型以用于 Upsert 存储过程,如下所示

CREATE TYPE [dbo].[CustomOrderRequestsType] AS TABLE(
[Customer_ID] [varchar](50) NOT NULL,
[Customer_Email] [varchar](50) NOT NULL,
[Customer_Notes] [nvarchar](Max) NOT NULL ) Go

下面是我执行此操作的存储过程,当我尝试在 Merge 语句中使用用户定义的 table 类型和输入参数时,它出现了一些错误。

ALTER PROCEDURE [dbo].[sp_UpsertCustomDesignReqsTable] 
 @OrderNumber VARCHAR(30)
,@Product_Id VARCHAR(50)
,@Purchase_amt VARCHAR(Max)
,@Details CustomOrderRequestsType READONLY
AS
BEGIN
    SET NOCOUNT ON;

MERGE [dbo].[CustomOrderReqs] AS TARGET
USING (VALUES (@OrderNumber, @Product_Id, ,@Purchase_amt, @Details) ) AS SOURCE  /*** Error Here **/
ON (SOURCE.[@OrderNumber] = TARGET.[Order Number]) 
    AND (SOURCE.[@Product_Id] = TARGET.[Product_Id] 
    AND (SOURCE.[Cutomer_Id] = TARGET.[Customer_Id]))
WHEN MATCHED THEN 
UPDATE SET TARGET.[Order Number] = @OrderNumber,
           TARGET.[Product_Id] = @NegItem,
           TARGET.[Purchase_amt] = @Purchase_amt,
           TARGET.[Customer_ID] = Source.[Customer_ID],
           TARGET.[Customer_Email = Source.[Customer_Email,
           TARGET.[Customer_Notes] = Source.[Customer_Notes]
WHEN NOT MATCHED BY TARGET THEN
INSERT VALUES (
                @OrderNumber,
                @NegItem,
                @Purchase_amt,
                Source.[Customer_ID],
                Source.[Customer_Email,
                Source.[Customer_Notes]);
END

通过上述查询,我​​在“源声明”行收到一条错误消息,消息如下:

Msg 137, Level 16, State 1, Procedure sp_UpsertCustomDesignReqsTable, Line 21 [Batch Start Line 7] Must declare the scalar variable "@Details"

如有任何建议,我们将不胜感激。

什么将变量添加到合并table?为什么不直接使用它们。

此外,如果您先解决所有语法错误,包括定义 @NegItem.

,您可能会发现事情变得更容易

最好的做法是在插入时明确列出列。

MERGE [dbo].[CustomOrderReqs] AS [TARGET]
USING @Details AS [SOURCE]
ON [SOURCE].OrderNumber = @OrderNumber 
    AND [SOURCE].Product_Id = @Product_Id 
    AND [SOURCE].Cutomer_Id = [TARGET].Customer_Id
WHEN MATCHED THEN 
UPDATE SET
    [TARGET].Customer_ID = [SOURCE].Customer_ID
    , [TARGET].Customer_Email = [SOURCE].Customer_Email
    , [TARGET].Customer_Notes = [SOURCE].Customer_Notes
WHEN NOT MATCHED BY TARGET THEN
INSERT (OrderNumber, ProductId, Amount, Customer_Id, Customer_Email, Customer_Notes)
VALUES (@OrderNumber, @Product_Id, @Purchase_amt, [SOURCE].[Customer_ID], [SOURCE].[Customer_Email, [SOURCE].[Customer_Notes]);

由于您在评论中添加了仅在值更改时更新的进一步要求,请考虑将行 WHEN MATCHED THEN 更改为

WHEN MATCHED THEN AND (
    -- Assume ID is never null
    [SOURCE].Customer_ID <> [TARGET].Customer_ID
    -- Handle null
    OR COALESCE([SOURCE].Customer_Email,'') <> COALESCE([TARGET].Customer_Email,'')
    -- Handle null
    OR COALESCE([SOURCE].Customer_Notes,'') <> COALESCE([TARGET].Customer_Notes,'')
)

但是我会在记录触发器中而不是在这里添加重复检测。

注意:Official Docs 解释了这一切以及更多内容。