问题:
我需要遍历一个表中的记录,提取员工编号并将该员工编号与另一个表进行比较,看看他们是否仍然是活跃的员工。如果他们不再是活跃的员工,我需要将此行中的数据传递到另一个存储过程。
研究
我已经搜索了很多,并意识到我不应该使用游标。不过我找到了以下例子:
然而,似乎他们使用pk循环记录。对于我的方案中的多个recod,员工编号可以相同
问题:
答案 0 :(得分:6)
由于您尚未完整描述您的情况,因此我们无法给出完整的答案,但一般来说,您希望避免 循环 在基于集合的语言中,如SQL而不是Cursors 本身(Cursosr的问题在于它们需要循环)。
在你的评论中,你提供了一些信息,你想要“循环通过第一个表,与第二个表进行比较,当比较失败时,我从第一个表中删除记录。在essense我正在删除从第一个不再与公司合作的员工表中记录。“
以下是在SQL中执行此操作的方法:
DELETE From FirstTable
WHERE FirstTable.EmployeeID NOT IN
(
SELECT SecondTable.EmployeeID
FROM SecondTable
WHERE SecondTable.Flag = 'Y'
)
不需要循环......
如果问题是你想使用预先存在的存储过程进行删除,那么有几种可能性:
首先,您可以提取存储过程的内容,并为这些先前的WHERE条件重新编写它们。我知道这是代码重复,它违反了某些人的DRY本能,但是,要理解SQL NOT 是面向对象的开发环境,有时代码重复必须发生。
第二个选项是重构存储过程,以便它可以接受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);
这避免了循环和Cusror问题,尽管许多人也不喜欢它。我自己更喜欢这个解决方案,主要是因为它的普遍性。
答案 1 :(得分:3)
如果当前员工表中没有匹配的行,这将删除员工数据表中的所有记录。
我认为您将DELETE FROM
替换为SELECT * FROM
,然后当您乐意删除结果时,请将其更改回DELETE
DELETE FROM
EmployeeDataTable
WHERE
NOT EXISTS
(SELECT
NULL
FROM
CurrentEmployees
WHERE
EmployeeDataTable.EmployeeID = CurrentEmployees.EmployeeID
)
编辑:刚看到你对Active标志的评论,这意味着查询可以改为
DELETE FROM
EmployeeDataTable
WHERE
EXISTS
(SELECT
NULL
FROM
CurrentEmployees
WHERE
EmployeeDataTable.EmployeeID = CurrentEmployees.EmployeeID
CurrentEmployees.IsActive <> 'Y'
)
答案 2 :(得分:2)
我会通过循环游标来做到这一点。您还可以向光标添加唯一ID,以便知道当前所在的行。
DECLARE @id uniqueidentifier
DECLARE @empName VARCHAR(50)
SELECT newId() AS Id, *
INTO #mytemp
FROM MyEmployees
ORDER BY EmpName
while EXISTS(SELECT TOP 1 1 FROM #mytemp)
BEGIN
--Get row from cursor to process
SELECT TOP 1 @id = Id, @empName = EmpName FROM #mytemp
--Do you processing here. Call other stored proc.
--Remove processed row from cursor.
DELETE FROM #mytemp WHERE Id = @id
END
DROP TABLE #mytemp
答案 3 :(得分:1)
您是否考虑过使用MERGE
声明:http://technet.microsoft.com/en-us/library/bb510625.aspx
你有以下条款:
然后,您可以根据匹配类型插入,更新或删除记录。您还可以将匹配操作输出到临时表以进行其他自定义操作。
例如,你可以这样做:
MERGE INTO Table1
USING Table2 ON Table1.EmployeeID = Table2.EmployeeID
WHEN MATCHED
THEN UPDATE SET Table1.SomeField = Table2.SomeOtherField
WHEN NOT MATCHED BY SOURCE
THEN DELETE
WHEN NOT MATCHED BY TARGET
THEN Insert (Name, Status) VALUES (EmployeeName, 'Active')
答案 4 :(得分:0)
有时,由于各种原因,游标是正确的解决方案。