我目前正在制作一个存储过程,用于更新产品详细信息。我想制作它(如果可能的话),这样只有在'值下输入的字段才能生成。执行时更新列,其余列保持不变。
ALTER PROCEDURE [dbo].[spUpdateProduct]
@ProductID int, @Brand nvarchar(30), @ModelNo nvarchar(9), @Description
nvarchar(50), @CostPrice decimal(6,2), @Stock int, @SalePrice decimal(6,2)
AS
BEGIN
SET NOCOUNT ON
UPDATE tblProduct
SET
Brand = @Brand,
ModelNo = @ModelNo,
[Description] = @Description,
CostPrice = @CostPrice,
Stock = @Stock,
SalePrice = @SalePrice
WHERE ProductID = @ProductID
END
这是我现在所拥有的。当我改变一个值时,它出错了,说我没有输入“品牌”的价值。这是产品ID'之后的下一个值。
Error when trying to update two fields (ProductID and CostPrice)
编辑:字段全部设置为' not null'当我创建表格时。
答案 0 :(得分:6)
我就是这样做的。具有无效参数
ALTER PROCEDURE [dbo].[spUpdateProduct]
@ProductID int,
@Brand nvarchar(30) = null,
@ModelNo nvarchar(9) = null, ..... (to all the parameters except @ProductID)
AS
BEGIN
SET NOCOUNT ON
UPDATE tblProduct
SET
Brand = isNull(@Brand, Brand),
ModelNo = isNull(@ModelNo, ModelNo),
[Description] = isNull(@Description, Description),...
WHERE ProductID = @ProductID
END
基本上,如果参数不为null,则只更新字段,否则保留旧值。
答案 1 :(得分:1)
您有两个问题 - (a)必须提供存储过程的参数(错误告诉您)和(b)未提供参数时该怎么做。对于第一个问题,请检查pass null值或使用SQL查询执行存储过程,如下所示:
exec spUpdateProduct 1, null, null, null, 140.99, null, null
对于问题(b),使用coalesce根据传递的值进行更新:
ALTER PROCEDURE [dbo].[spUpdateProduct]
@ProductID int, @Brand nvarchar(30), @ModelNo nvarchar(9), @Description
nvarchar(50), @CostPrice decimal(6,2), @Stock int, @SalePrice decimal(6,2)
AS
BEGIN
SET NOCOUNT ON
UPDATE t
SET
Brand = coalesce(@Brand, t.Brand),
ModelNo = coalesce(@ModelNo, t.ModelNo),
[Description] = coalesce(@Description, t.Description),
CostPrice = coalesce(@CostPrice, t.CostPrice),
Stock = coalesce(@Stock, t.Stock),
SalePrice = coalesce(@SalePrice, t.SalePrice)
FROM tblProduct as t
WHERE ProductID = @ProductID
END
答案 2 :(得分:0)
经过一段时间的思考,我想出了一个不使用动态 sql 的解决方案,也解决了 coalese
和 isNull
方法无法解决的问题。注意:最少的测试……看起来确实增加了一点开销……但是拥有这种能力可能会让您的客户端代码具有灵活性。
表架构:
FirstName NVARCHAR(200)
LastName NVARCHAR(200)
BirthDate DATE NULL
Activated BIT
Xml 参数:
DECLARE @param =
N'<FirstName>Foo</FirstName>
<LastName>Bar</LastName>
<BirthDate>1999-1-1</BirthDate>
<Activated>1</Activated>'
UPDATE [dbo].[UserMaster]
[FirstName] = case when @param.exist('/FirstName') = 1 then @param.value('/FirstName[1]','nvarchar(200)') else [FirstName] end,
[LastName] = case when @param.exist('/LastName') = 1 then @param.value('/LastName[1]','nvarchar(200)') else [LastName] end,
[BirthDate] = case when @param.exist('/BirthDate') = 1 then @param.value('/BirthDate[1]','date') else [BirthDate]end,
[Activated] = case when @param.exist('/Activated') = 1 then @param.value('/Activated[1]','bit') else [Activated] end
WHERE [UserMasterKey] = @param.value('/UserMasterKey[1]','bigint')
这将允许您传入一个 XML 参数,包含您想要的任何字段并更新该字段。请注意,在此上下文中将字段设置为等于自身,例如 [FirstName] = [FirstName],完全没问题。引擎会对此进行优化。
现在,这是@Anand 和@r.net 答案的更复杂的解决方案,但是它确实解决了一些评论者指出的“设置可空值”问题。
我喜欢他们的解决方案的优雅,但希望能够在可空列上设置 NULL,同时如果我不为该字段传递参数,仍然保留使用默认字段值的能力。在这种情况下,使用 null 检查作为默认值的基础填补了漏洞并挖掘了另一个漏洞,可以这么说,因为它们不允许将字段显式更新为 null。
传递 xml 参数允许您这样做,而无需采用动态 sql 方法。
我也会考虑使用 Table-valued parameters,因为我相信使用这些可以有类似的解决方案。