Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用多个表源合并(用户定义的表类型和输入参数)_Sql_Sql Server_Tsql_Merge_Upsert - Fatal编程技术网

Sql 使用多个表源合并(用户定义的表类型和输入参数)

Sql 使用多个表源合并(用户定义的表类型和输入参数),sql,sql-server,tsql,merge,upsert,Sql,Sql Server,Tsql,Merge,Upsert,我试图将数据插入一个名为“CustomOrderReqs”的表中。我将使用用户定义的表类型和存储过程的输入参数定期向该表插入/更新数据。我最后的表格如下: 我定义了一个用户定义的表类型,用于Upsert存储过程,如下所示 CREATE TYPE [dbo].[CustomOrderRequestsType] AS TABLE( [Customer_ID] [varchar](50) NOT NULL, [Customer_Email] [varchar](50) NOT NULL, [Cust

我试图将数据插入一个名为“CustomOrderReqs”的表中。我将使用用户定义的表类型和存储过程的输入参数定期向该表插入/更新数据。我最后的表格如下:

我定义了一个用户定义的表类型,用于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语句中使用用户定义的表类型和输入参数时,它会出现一些错误

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,16级,状态1,程序sp_UpsertCustomDesignReqsTable,第21行[批次开始第7行] 必须声明标量变量“@Details”


任何建议都将不胜感激。

如何将变量添加到合并表中?为什么不直接使用它们呢

此外,如果您首先解决所有语法错误,包括定义
@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 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,'')
)
匹配时,然后(
--假设ID从不为null
[来源].Customer\u ID[目标].Customer\u ID
--句柄空值
或合并([SOURCE]。客户电子邮件“”)合并([TARGET]。客户电子邮件“”)
--句柄空值
或合并([SOURCE].Customer\u Notes'))合并([TARGET].Customer\u Notes'))
)
但是,我想在日志触发器中添加重复检测,而不是在这里


注意:详细信息是一个表格,你把它当作一列来处理吗?请解释一下您的行(包括var和表var)实际上要做什么。感谢您对@DaleK的评论。我试图使用用户定义的表类型
(@Details)
(客户Id)
来验证
CustomOrderReqs
表中的匹配记录或现有记录,以便进行更新(如果存在)。它不仅是正在使用的信息,而且还使用
@OrderNumber&@Product\u Id
列,在
@Details
用户定义的表类型之外。在上述过程中,您可以在
匹配后的
语句上方看到相同的内容。最后一个问题是,如何仅更新正在修改的列。。在这种情况下,我们可以去掉更新集的
OrderNumber、Product\u Id和Cutomer\u Id
列,因为我们总是在验证这些列的匹配情况,以便进入更新逻辑。但是,我如何才能只更新正在修改的列
(客户ID、客户电子邮件、客户备注)
,而不是更新现有记录中的原始值(无论有无更改)。这个问题的原因是我已经为
customordereqs
表创建了一个历史记录表,并且不想创建重复项对不起,我的错了。当我们检查匹配项以更新现有记录时,我们可以从Update语句中删除列
OrderNumber、Product\u Id和Cutomer\u Id
,如下所示。`匹配后,更新集[TARGET]。购买金额=@Purchase\u amt[TARGET]。客户Id=[SOURCE]。客户Id[TARGET]。客户电子邮件=[SOURCE].Customer\u Email[TARGET].Customer\u Notes=[SOURCE].Customer\u Notes如果与TARGET不匹配,则“但是,我只想更新列
(客户ID、客户电子邮件、客户备注
,它们只被修改,而不是每次更新逻辑出错时都更新它们。您可以忽略
@negItem
,假设它是
@Product\u ID
,我已经创建了一个跟踪更改的历史记录或日志表,并且我不想记录没有对t进行任何更改的记录。)他创建了正在更新的列