Problem:
I need to loop through the records in one table, pulling the employee number and comparing this employee number against another table to see if they're still active employees. If they are no longer active employees I need to pass the data from this row into another stored proc.
Research:
I've googled around quite a bit and realize that I shouldn't use cursors for this. I did however, find the following examples:
However, it seems like they use a pk to loop through the records. Employee numbers can be the same for multiple recods in my scenario
Questions:
Since you haven't given us a full description of your situation, we cannot give a complete answer, however, in general, it's Loops that you want to avoid in a set-based language like SQL and not Cursors per se (the problem with Cursosr is that they require the Loops).
In your comments you provide a little bit more information in that you want to " loop through first table, compare to second table, and when the compare fails i delete records from first table. In essense I'm deleting recods from the first table of employees who are no longer with the company. "
Here is how you can do this in SQL:
DELETE From FirstTable
WHERE FirstTable.EmployeeID NOT IN
(
SELECT SecondTable.EmployeeID
FROM SecondTable
WHERE SecondTable.Flag = 'Y'
)
No Loops are needed ...
If the issue then is that you want to use a pre-existing Stored Procedure to do the deletion, then there are a several possibilities:
First, you can extract the contents of the Stored Procedure and re-write them for these preceding WHERE conditions. I understand that this is code duplication and that it violates some people's DRY instincts, however, understand that SQL is NOT an Object-Oriented development environment and that sometimes code duplication has to happen.
The second option would be to refactor the stored procedure so that it could accept a TableParameter for its EmployeeId's to Delete. This is complicated though, and we would need to see that stored procedure to advise you on it.
The third option would be to use string aggregation to build dynamic SQL to call the stored procedure for each EmployeeID to be deleted like so:
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);
This avoids both the Looping and the Cusror problems, though many dislike it also. I prefer this solution myself, largely because of its generality.
This will delete all records from your employee data table if there are no matching rows in your current employees table.
I'd sugest you replace the DELETE FROM
with SELECT * FROM
and then when you're happy to delete the results change it back to DELETE
DELETE FROM
EmployeeDataTable
WHERE
NOT EXISTS
(SELECT
NULL
FROM
CurrentEmployees
WHERE
EmployeeDataTable.EmployeeID = CurrentEmployees.EmployeeID
)
EDIT: Just saw your comment about the Active flag, this means the query can be changed to
DELETE FROM
EmployeeDataTable
WHERE
EXISTS
(SELECT
NULL
FROM
CurrentEmployees
WHERE
EmployeeDataTable.EmployeeID = CurrentEmployees.EmployeeID
CurrentEmployees.IsActive <> 'Y'
)
I would do this by looping through a cursor. You can also add a unique ID to the cursor so you know which row you are currently on.
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
Have you considered using the MERGE
statement : http://technet.microsoft.com/en-us/library/bb510625.aspx
You have clauses for :
You can then insert, update or delete records depending on the match type. You can also output the action from match to a temporary table for additional custom operations.
For instance, you can do :
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')
Sometimes, cursors are the right solution for a variety of reasons.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.