2017-10-12 90 views
0

下面是我正在运行的查询。我的问题似乎在下面的INSERT语句中。我所拥有的是FeatureKeys的列表,我使用ROW_NUMBER()逐个遍历这个列表,以便一次输入每个单独的FeatureKey。问题是,前几个FeatureKeys输入正确没有问题,但对列表的末尾它说我试图插入NULL值到FeatureKey列。作为一个例子,我有一个4个FeatureKeys的列表,然后尝试逐个输入每个FeatureKey,前两个get正确插入,最后说我试图向FeatureKey列插入NULL值。我曾尝试在循环的不同部分将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 

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

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

+2

这看起来像一个非常复杂的查询,可以用一个基于集合的查询来完成。也许你可以提供你的表的样子和你期待的结果,并且帮助你实现你想要的更容易,而不是修复一个不必要地使用while循环的查询(很可能)。 – ZLK

+1

问题证明 - 在最后一个WHILE循环中,将'INSERT INTO ATI_FeatureInspection.dbo.Position'语句替换为:'SELECT @InspectionKey,@Count + 1,@ FeatureKey',并查看是否输出NULL。另外,将'SET @Count = @Count + 1'语句放在'INSERT'之前,以避免必须在'VALUES'语句中将'@ Count'变量加1。 –

+0

@LaughingVergil我没有看到任何NULLs这一切都出来正确 –

回答

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