插入查询正在尝试插入空值,但值不应为空

时间:2017-10-12 23:08:33

标签: sql-server

以下是我正在运行的查询。我的问题似乎在下面的INSERT声明中。我有一个FeatureKeys列表,我使用ROW_NUMBER()逐个遍历此列表,以便一次输入每个FeatureKey。问题是前几个FeatureKeys输入正确没问题但是在列表末尾它说我试图将NULL值插入FeatureKey列。作为一个例子,我有一个4个FeatureKeys的列表,然后我尝试逐个输入每个FeatureKey,前两个正确插入,最后说我试图将NULL值插入FeatureKey列。我已经尝试将FeatureKey值打印到循环的不同部分的控制台,并且很好地逐个打印出所有值。只有当我尝试执行INSERT语句时,无论出于何种原因,FeatureKey变量都是NULL。

DECLARE @Count INT, @RowFeature INT,  @MaxParts INT, @TotalNewFeatures INT, @InspectionKey INT, @FeatureKey INT 
SET @InspectionKey =
    (SELECT Inspection_Key FROM ATI_FeatureInspection.dbo.Inspection WHERE Op_Key = 562634);  
SET @TotalNewFeatures = 
    (SELECT COUNT(Features.Feature_Key)
    FROM ATI_FeatureInspection.dbo.Features
    WHERE NOT EXISTS(
            SELECT *
            FROM ATI_FeatureInspection.dbo.Position 
            WHERE Features.Feature_Key = Position.Feature_Key
                AND Inspection_Key_FK =
                        (SELECT Inspection.Inspection_Key
                        FROM ATI_FeatureInspection.dbo.Inspection
                        WHERE Op_Key = 562634))
        AND Part_Number_FK =
                (SELECT Part_Number
                FROM ATI_FeatureInspection.dbo.Operation
                WHERE Op_Key = 562634)
        AND Operation_Number_FK =
                (SELECT Operation_Number
                FROM ATI_FeatureInspection.dbo.Operation
                WHERE Op_Key = 562634));  

SET @Count = 0;  
SET @RowFeature = 0  
SET @MaxParts = 13 

WHILE(@RowFeature < @TotalNewFeatures)  
BEGIN  
    SET @RowFeature = @RowFeature + 1;  

    SET @FeatureKey =
            (SELECT Feature_Key
            FROM (
                    SELECT ROW_NUMBER() OVER(ORDER BY Features.Feature_Key ASC) AS RowNumber, Features.Feature_Key
                    FROM ATI_FeatureInspection.dbo.Features  
                    WHERE NOT EXISTS(
                            SELECT *
                            FROM ATI_FeatureInspection.dbo.Position 
                            WHERE Features.Feature_Key = Position.Feature_Key
                                AND Inspection_Key_FK = 
                                        (SELECT Inspection.Inspection_Key
                                        FROM ATI_FeatureInspection.dbo.Inspection 
                                        WHERE Op_Key = 562634))
                        AND Part_Number_FK =
                                (SELECT Part_Number
                                FROM ATI_FeatureInspection.dbo.Operation
                                WHERE Op_Key = 562634)
                        AND Operation_Number_FK =
                                (SELECT Operation_Number
                                FROM ATI_FeatureInspection.dbo.Operation
                                WHERE Op_Key = 562634)) AS foo
            WHERE RowNumber = @RowFeature); 

    WHILE(@Count < @MaxParts)  
    BEGIN
        INSERT INTO ATI_FeatureInspection.dbo.Position(Inspection_Key_FK, Piece_ID, Feature_Key)
        VALUES(@InspectionKey, @Count + 1, @FeatureKey)  
        SET @Count = @Count + 1  
    END  

    SET @Count = 0  
END

下面是我的数据库图表。有一个WinForms程序,用户输入一个OpKey和一个LotSize。 OpKey属于特定的部件号和操作号对,并且多个OpKey可以具有相同的部件和操作号。用户可以将功能添加到部件和操作编号对(NOT AN OPKEY),使2个不同或更多的OpKey可以使用相同的功能,而无需为每个OpKey添加功能。我在这里要做的是为用户想要检查的每个部分插入功能,这也是LotSize。作为示例,用户将3个特征添加到PartNumber = 386022和OperationNumber = 150的组合中。具有该组合的大约7个不同的OpKeys。我们将使用其中两个。使用LotSize = 10时,用户使用OpKey = 26266进行打孔。因此,此查询创建10个部分,其中3个要素与每个部分关联。如果我然后打入OpKey = 468753和LotSize = 6,它与相同的零件和操作编号相关联,则此查询将插入6个零件,每个零件具有相同的3个特征。现在,此查询还将检测事后是否添加了任何新功能,并相应地添加这些功能。因此,如果用户在上面的相同部件和操作编号组合中添加了新功能,当用户进入OpKey = 26266时,用户将无法再选择批量,因为它已经创建并将新功能添加到每个部件中那次检查。所以基本上只是添加创建具有必要功能的部件,以便在Position表中进行检查。

[DataBaseDiagramImage] [1] [1]:https://i.stack.imgur.com/svbgJ.png

1 个答案:

答案 0 :(得分:0)

您的问题在这里:

WHERE RowNumber = @RowFeature

您正在向要查询的其中一个表中添加行,用于从返回的信息中排除项目。您还在递增@RowFeature值。组合工作如下:

  • 阅读第一个功能(@RowFeature = 1)
  • 将该项添加到Position
  • 阅读下一个功能(@RowFeature = 2)
    • 由于向Position表添加了第一个功能,因此在阅读下一个功能时不会返回第一个功能
    • 这意味着第二个功能在RowNumber 1中,第三个功能在RowNumber 2中
  • 将包含RowNumber 2(功能3)的项目添加到Position
  • 重复完成

鉴于此结构,解决方案是将WHERE RowNumber = @RowFeature替换为WHERE RowNumber = 1

然而,更好的处理方法是使这个代码更加基于集合,而不是逐行处理数据行(RBAR)。如果我们创建一个小数字表,例如:

,这将更容易
CREATE TABLE Nums(num int primary key clustered)
INSERT INTO Nums(num)
SELECT TOP 10000 ROW_NUMBER() OVER(ORDER BY t1.number) AS N
FROM master..spt_values t1 
CROSS JOIN master..spt_values t2

在您的情况下,您可以在一个命令中插入所有@maxParts行。 这样的事情应该有效:

WITH foo as (
    SELECT ROW_NUMBER() OVER(ORDER BY Features.Feature_Key ASC) AS RowNumber, 
        Features.Feature_Key
    FROM ATI_FeatureInspection.dbo.Features  
    WHERE NOT EXISTS(
        SELECT *
        FROM ATI_FeatureInspection.dbo.Position 
        WHERE Features.Feature_Key = Position.Feature_Key
            AND Inspection_Key_FK = (
                SELECT Inspection.Inspection_Key
                FROM ATI_FeatureInspection.dbo.Inspection 
                WHERE Op_Key = 562634
                )
        )
        AND Part_Number_FK = (
            SELECT Part_Number
            FROM ATI_FeatureInspection.dbo.Operation
            WHERE Op_Key = 562634
        )
        AND Operation_Number_FK = (
            SELECT Operation_Number
            FROM ATI_FeatureInspection.dbo.Operation
            WHERE Op_Key = 562634
        )
    ) 
INSERT INTO ATI_FeatureInspection.dbo.Position(Inspection_Key_FK, Piece_ID, Feature_Key)
SELECT @InspectionKey, Nums(num), foo.Feature_Key, 
FROM foo
CROSS JOIN Nums 
WHERE num <= @maxParts