通过加入从CTE中删除

时间:2014-03-31 12:48:55

标签: sql sql-server-2008

我正在尝试使用sql表实现FIFO队列。

我有以下SQL(修改后发布),连接和参数使用对此过程的工作方式很重要。

With cte as (
   select top(1) q.* from queue q with (readpast)
   inner join MyTable a on q.id = a.myTableID AND myTable.procID = @myParam
   order by q.Data asc
)
delete from cte
    output
      deleted.ID,
      deleted.col1

运行此语句将返回错误'视图或函数'cte'不可更新,因为修改会影响多个基表。

我理解为什么会抛出错误,我无法弄清楚的是如何解决它。任何建议将不胜感激!

3 个答案:

答案 0 :(得分:19)

您可以在CTE中使用exists()代替内部联接MyTable

with cte as 
(
  select top(1) q.id,
                q.col1
  from queue q with (readpast)
  where exists(
              select *
              from  MyTable a 
              where  q.id = a.myTableID AND 
                     a.procID = @myParam
              )
  order by q.Data asc
)
delete from cte
output deleted.ID, deleted.col1;

答案 1 :(得分:4)

这样的东西?

With cte as (
   select top(1) q.* from queue q with (readpast)
   inner join MyTable a on q.id = a.myTableID AND myTable.procID = @myParam
   order by q.Data asc
)
delete from queue
Where ID in (Select Id from cte)

答案 2 :(得分:1)

这里强迫使用CTE。你可以简单地说:

 DELETE FROM [queue]
  WHERE id IN ( 
    SELECT TOP 1 
           q.id 
      FROM [queue] q WITH (READPAST)
           INNER JOIN 
           MyTable a ON q.id = a.myTableID 
                    AND myTable.procID = @myParam
    ORDER BY q.Data ASC)

如果你想使用CTE,我喜欢@ sarin的答案,但使用的是EXIST:

WITH cte AS (
  SELECT TOP 1 
         q.id 
    FROM [queue] q WITH (READPAST)
         INNER JOIN 
         MyTable a ON q.id = a.myTableID 
                  AND myTable.procID = @myParam
   ORDER BY q.Data ASC
)
DELETE [queue] 
 WHERE EXISTS(SELECT 1 FROM cte WHERE cte.id = [queue].id)