使用CTE时执行CRUD操作时,对象名称“Table”无效

时间:2012-06-06 07:50:13

标签: sql sql-server tsql crud common-table-expression

您好我正在创建My SP,根据我的select语句给出的结果插入和检测记录。

这是我的示例代码:

DECLARE @PickListBatchName varchar(200),
@PartNumber varchar(50),
@QTY int;

SET @PickListBatchName='TEST1';
SET @PartNumber='PN1';
SET @QTY=1;


      --STEP 1 Add Result to TempTable
      With SN as
      (
        SELECT TOP (@QTY) 
           pb.PickListBatchId
           ,pt.PickListTRANId
           ,pt.SerialNumber
           ,pt.Createdby
           ,pt.CreatedDT
FROM PickListTRAN pt 
            LEFT JOIN PickListBatchDetail pdb ON pdb.PickListBatchDetailId=pt.PickListBatchDetailId
            LEFT JOIN PickListBatch pb ON pdb.PickListBatchId=pb.PickListBatchId
where  pb.PickListBatchName=@PickListBatchName AND pdb.PartNumber=@PartNumber
      )


    --STEP 2: INSERT SN TO PicklistTranCancel
    INSERT INTO PickListTRANCancel
   (
   PickListBatchId
   ,SerialNumber
   ,CreatedBy
   ,CreatedDT
   ) 
   (SELECT  
           PickListBatchId,
           SerialNumber,
           Createdby,
           CreatedDT
    FROM SN);

    --STEP 3: DELETE Records on PicklistTran

    DELETE FROM PicklistTran where picklistTranId IN (SELECT PickListTRANId FROM SN)

结果:

(1 row(s) affected)
Msg 208, Level 16, State 1, Line 49
Invalid object name 'SN'.  --error on delete statement

在步骤3中,delete语句无法读取SN表。也许我错过了那部分的东西。

表示感谢

4 个答案:

答案 0 :(得分:6)

在您的代码中,CTE只能在insert语句之前访问。如果需要访问CTE表,请尝试将CTE数据填充到@TempTable中,然后在删除语句中访问它。您可以修改代码以将值存储到临时表中

 INSERT INTO PickListTRANCancel

  (
  PickListBatchId
  ,SerialNumber
  ,CreatedBy
  ,CreatedDT
  ) 
Output   Inserted.PickListBatchId,Inserted.SerialNumber,Inserted.CreatedBy,
Inserted.CreatedDT into @TempTable
  (SELECT  
       PickListBatchId,
       SerialNumber,
       Createdby,
       CreatedDT
FROM SN);

   DELETE FROM PicklistTran where picklistTranId IN
   (SELECT PickListTRANId FROM @TempTable)

我尚未验证代码,但这样您就可以构建查询。

答案 1 :(得分:2)

CTE是一个临时结果集,它在单个SELECT,INSERT,UPDATE,DELETE,MERGE或CREATE VIEW语句的执行范围内定义。 - http://msdn.microsoft.com/en-us/library/ms190766(v=sql.105).aspx

如上所述,CTE在第二个陈述中不再可用,它们仅适用于一个陈述。

答案 2 :(得分:1)

感谢@benni_mac_b和@praveen,这就是我的尝试。我只是用来创建TempTable而不是使用WITH。

DECLARE @PickListBatchName varchar(200),
@PartNumber varchar(50),
@QTY int;

SET @PickListBatchName='TEST1';
SET @PartNumber='PN1';
SET @QTY=1;

Declare @MyTable table 
(
     PickListBatchId int,
     PickListTRANId int,
    SerialNumber varchar(50),
    Createdby varchar(50),
    CreatedDT datetime
);


 --STEP 1: insert to temptable 
 INSERT INTO @MyTable
                    (
           PickListBatchId,
           PickListTRANId,
           SerialNumber,
           Createdby,
           CreatedDT
                    )
SELECT TOP (@QTY) 
           pb.PickListBatchId
           ,pt.PickListTRANId
           ,pt.SerialNumber
           ,pt.Createdby
           ,pt.CreatedDT
FROM PickListTRAN pt 
            LEFT JOIN PickListBatchDetail pdb ON pdb.PickListBatchDetailId=pt.PickListBatchDetailId
            LEFT JOIN PickListBatch pb ON pdb.PickListBatchId=pb.PickListBatchId
where  pb.PickListBatchName=@PickListBatchName AND pdb.PartNumber=@PartNumber


    --STEP 2: INSERT SN TO PicklistTranCancel
    INSERT INTO PickListTRANCancel
   (
   PickListBatchId
   ,SerialNumber
   ,CreatedBy
   ,CreatedDT
   ) 
   SELECT  
   PickListBatchId,
   SerialNumber,
   Createdby,
   CreatedDT
   FROM @MyTable

   --STEP 3: DELETE
   DELETE FROM PicklistTran where picklistTranId IN (SELECT PickListTRANId FROM @MyTable)

答案 3 :(得分:0)

CTE范围仅适用于一个语句,您不能使用它两次。您可以使用临时表来存储CTE的值