如何在没有pk的存储过程中循环临时表

Ste*_*a D 5 sql t-sql sql-server stored-procedures

问题:

我需要在一个表中循环记录,拉出员工编号并将该员工编号与另一个表进行比较,以查看他们是否仍然是活跃的员工.如果他们不再是活跃的员工,我需要将此行中的数据传递到另一个存储过程.

研究:

我已经google了很多,并意识到我不应该使用游标.但是,我找到了以下示例:

  1. http://ask.sqlservercentral.com/questions/7969/loop-through-records-in-a-temporary-table.html
  2. http://eedle.com/2010/11/11/looping-through-records-in-sql-server-stored-procedure/

但是,似乎他们使用pk来遍历记录.在我的方案中,多个recods的员工编号可以相同

问题:

  1. 是否有可能实现我没有游标的尝试?
  2. 如果可能,我将如何使用非唯一列获取每一行?

RBa*_*ung 6

既然你还没有完整地描述你的情况,我们就无法给出一个完整的答案,但是,一般来说,它是你想要在基于集合的语言中避免的循环,比如SQL而不是游标本身(问题是Cursosr是他们需要循环).

在你的评论中,你提供了一些信息,你想要" 循环第一个表,与第二个表比较,当比较失败时,我从第一个表中删除记录.在essense我正在从第一个表中删除recods不再与公司合作的员工. "

以下是在SQL中如何执行此操作:

DELETE  From FirstTable
WHERE   FirstTable.EmployeeID NOT IN
    (
        SELECT  SecondTable.EmployeeID 
        FROM    SecondTable
        WHERE   SecondTable.Flag = 'Y'
    )
Run Code Online (Sandbox Code Playgroud)

不需要循环......


如果问题是您想要使用预先存在的存储过程进行删除,那么有几种可能性:

首先,您可以提取存储过程的内容,并为这些先前的WHERE条件重新编写它们.我知道这是代码重复,它违反了某些人的DRY本能,但是,要了解SQL 不是面向对象的开发环境,有时代码重复必须发生.

第二种选择是重构存储过程,以便它可以接受TableParameter以使其EmployeeId删除.虽然这很复杂,但我们需要查看存储过程以便为您提供建议.

第三种选择是使用字符串聚合来构建动态SQL,以便为每个EmployeeID调用存储过程,如下所示:

DECLARE @sql As NVarchar(MAX);  
SET     @sql = N'';

SELECT  @sql = @sql + ' 
    EXEC YourProc ''' + CAST(EmployeeID As NVARCHAR(MAX)) + '''; '
FROM    FirstTable
WHERE   FirstTable.EmployeeID IN
    (
        SELECT  SecondTable.EmployeeID 
        FROM    SecondTable
        WHERE   SecondTable.Flag = 'Y'
    )

EXEC(@sql);
Run Code Online (Sandbox Code Playgroud)

这避免了循环和Cusror问题,尽管许多人也不喜欢它.我自己更喜欢这个解决方案,主要是因为它的普遍性.