首页 > 解决方案 > 运行特殊过程时 AdventureWorks 2012 SQL 错误

问题描述

我正在创建一个特殊程序,将输入的折扣应用于输入的应用数量,但我不断收到错误消息,其中 PK 不能为空。为什么它不自动增加行?

GO
CREATE PROCEDURE Sales.uspExcesInvSale
    @DiscountPct smallmoney,
    @ProductInventory int
AS
SET IDENTITY_INSERT Sales.SpecialOffer ON
    INSERT INTO Sales.SpecialOffer (SpecialOfferID, Description, DiscountPct, Type, Category, StartDate, EndDate, MinQty)
    VALUES ((SELECT MAX(SpecialOfferID)+1 FROM SpecialOffer), 'New Sale', @DiscountPct, 'Excess Inventory', 'Direct', DATEADD(DAY,5,GETDATE()), DATEADD(DAY,7,GETDATE()), @ProductInventory);

    INSERT INTO Sales.SpecialOfferProduct (ProductID)
    SELECT ProductID
    FROM Production.ProductInventory 
    GROUP BY ProductID 
    HAVING SUM(Quantity) > (@ProductInventory)
SET IDENTITY_INSERT Sales.SpecialOffer OFF;
GO
BEGIN TRY
EXEC Sales.uspExcesInvSale .5, 1800;
END TRY
BEGIN CATCH
    SELECT  
    ERROR_NUMBER() AS ErrorNumber  
    ,ERROR_SEVERITY() AS ErrorSeverity  
    ,ERROR_STATE() AS ErrorState  
    ,ERROR_PROCEDURE() AS ErrorProcedure  
    ,ERROR_LINE() AS ErrorLine  
    ,ERROR_MESSAGE() AS ErrorMessage;  
END CATCH;
GO

收到的错误是错误编号 515 严重性 16 错误状态 2 错误过程 Sales.uspExcesInvSale 错误行 9 错误消息 无法将值 NULL 插入列“SpecialOfferID”,表“AdventureWorks2012.Sales.SpecialOfferProduct”;列不允许空值。插入失败。

标签: sql-servertsqlstored-proceduresadventureworks

解决方案


错误在这里 - 您没有为 SpecialOfferID 插入值,这是该表所必需的。

INSERT INTO Sales.SpecialOfferProduct (ProductID)   -- These should have
    SELECT ProductID                                -- SpecialOfferID as well
    FROM Production.ProductInventory 
    GROUP BY ProductID 
    HAVING SUM(Quantity) > (@ProductInventory)

我相信这两张桌子的PK是

  • SpecialOffer:称为 SpecialOfferID、int、IDENTITY 的单列(例如,是一个自动增量)
  • SpecialOfferProduct:两个 int 列,其中只有一个是 IDENTITY。另一个是SpecialOfferID

因此,在插入 SpecialOfferProduct 时,您需要明确指定 SpecialOfferID,因为它不会自动输入。PK 的另一部分(我相信是 SalesOrderDetailID)是一个 IDENTITY,你可以让它发挥作用。

相比之下 - 鉴于 SpecialOffer 的 PK 是一个 IDENTITY 列,我建议让它发挥作用。删除 IDENTITY_INSERTSET语句,然后不要在插入语句中包含值。它将自动创建下一个 ID 值。

我猜你想从第一个插入(例如,从 SpecialOffer)中获取相关的 SpecialOfferID,然后在第二个插入中使用它(例如,进入 SpecialOfferProduct)。

您可以使用SCOPE_IDENTITY()获取“最后插入的 ID” 。

通过这些更改,这是一组示例代码(遗憾的是未经测试,因为我没有设置数据库)。

注意 - 我也不是 100% 确定你在用这些插件做什么(尤其是第二个)——你需要检查它是否在做你想做的事情。这个答案与无法插入的错误有关。

DECLARE @NewID int

INSERT INTO Sales.SpecialOffer (Description, DiscountPct, Type, Category, StartDate, EndDate, MinQty)
    VALUES ('New Sale', @DiscountPct, 'Excess Inventory', 'Direct', DATEADD(DAY,5,GETDATE()), DATEADD(DAY,7,GETDATE()), @ProductInventory);

SET @NewID = SCOPE_IDENTITY()

INSERT INTO Sales.SpecialOfferProduct (SpecialOfferID, ProductID)
    SELECT @NewID, ProductID
    FROM Production.ProductInventory 
    GROUP BY ProductID 
    HAVING SUM(Quantity) > (@ProductInventory)

推荐阅读