我有一个ProductsAttributesValues表,其中包含
Id ProductId AttributeId Value ORDER
-------------------------------------------------
具有属性(相同ProductId / AttributeId)的产品可以具有多个值但具有不同的订单。我有一个类型,
CREATE TYPE [dbo].[ProductsAttributesValuesType] AS TABLE
(
[AttributeId] [INT],
[Value] [NVARCHAR](MAX)
)
我在我的存储过程中将此ProductsAttributesValuesType
作为table-value-parameter传递给ProductId参数。现在我需要的东西看起来很简单,但我被困住了。 ProductsAttributesValuesType
中的信息来自用户界面。所以,
1)如果值为null或为空或空白,则我无需执行任何操作,并使用相同的ProductId / AttributeId从ProductsAttributesValues
删除所有现有记录。
2)如果值不为null或非空或非空白,则可能存在单个值或多个值(ProductsAttributesValuesType
中的多个记录)。如果存在单个值,则在没有现有值时需要插入,如果存在值则更新。如果有多个值(ProductsAttributesValuesType
中有多个记录),如果不存在现有值,则需要插入所有值,如果存在值则更新/插入。
一种方法是简单地删除具有相同ProductId / AttributeId的所有ProductsAttributesValues
表。然后插入具有非空值的值。但我认为效率不高。
更新:目前,我首先删除所有多值属性值。接下来,我将删除值为空的所有属性值。接下来,我插入/更新单值属性值。接下来,我将插入多个valeus属性值。
答案 0 :(得分:4)
避免使用Merge语句将其分解为三个语句并将其全部包装在一个Transaction中,如下所示
CREATE Procedure Upserting_To_ProductsAttributesValues
@ProductsAttributesValuesType [dbo].[ProductsAttributesValuesType] READONLY
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
-- Delete values
DELETE FROM ProductsAttributesValues
FROM ProductsAttributesValues T INNER JOIN @ProductsAttributesValuesType P
ON T.AttributeId = P.AttributeId
WHERE P.Value IS NULL OR RTRIM(LTRIM(P.Value)) = ''
-- Update Statement
UPDATE T
SET T.Value = P.Value
FROM ProductsAttributesValues T INNER JOIN @ProductsAttributesValuesType P
ON T.AttributeId = P.AttributeId
-- Insert Statement
INSERT INTO ProductsAttributesValues (AttributeId, Value)
SELECT AttributeId, Value
FROM @ProductsAttributesValuesType P
WHERE NOT EXISTS (SELECT 1
FROM ProductsAttributesValues
WHERE AttributeId = P.AttributeId)
COMMIT TRANSACTION; --<-- If nothing went wrong
END TRY
BEGIN CATCH
-- Now make use of ERROR Functions to get detailed information
-- about the error, these functions are only allowed in catch block
SELECT ERROR_MESSAGE() AS [ERROR_MESSAGE]
,ERROR_LINE() AS [ERROR_LINE]
,ERROR_NUMBER() AS [ERROR_NUMBER]
END CATCH
END
注意的
我建议避免合并声明的原因参见本文作者:Aaron Bertrand Use Caution with SQL Server's MERGE Statement