使用多个 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 解释了这一切以及更多内容。
我正在尝试将数据更新到一个名为“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 解释了这一切以及更多内容。