17

I have two tables:

Employees(EmployeeID, EmployeeName, EmployeeStatus, BasicSalary) and

EmployeePayroll (PayrollID, EmployeeID, VoucherNo, BasicSalary, SalaryMonth)

I want to make a for each loop for every employee in the first table so that I can insert dummy data like (0, EmployeeID,0 ,0 ,0) into the second table.

I tried to make it with a for loop but I could not make it, so is there a for each loop in MS SQL Server??

Malachi
  • 3,205
  • 4
  • 29
  • 46
HAJJAJ
  • 3,667
  • 14
  • 42
  • 70

7 Answers7

29

If you really require a loop, you can use a cursor. They are horribly inefficient, so you should avoid unless you absolutely require it:

DECLARE c CURSOR READ_ONLY FAST_FORWARD FOR
    SELECT EmployeeID
    FROM Employees

DECLARE @id Int

-- Open the cursor
OPEN c

FETCH NEXT FROM c INTO @id
WHILE (@@FETCH_STATUS = 0)
BEGIN
    INSERT INTO EmployeePayroll
    SELECT 0, @id, 0, 0, 0

    -- do other stuff

    FETCH NEXT FROM c INTO @id
END

-- Close and deallocate the cursor
CLOSE c
DEALLOCATE c
David Duffett
  • 3,145
  • 2
  • 26
  • 27
  • 9
    +1 for the performance warning: but "not very efficient" is an understatement; if you want to bring you server to its knees, use cursors. – E.J. Brennan May 02 '11 at 10:52
  • 4
    Right you are. I've corrected my grave mistake to "horribly inefficient" ;) – David Duffett May 02 '11 at 10:55
  • @DavidDuffett - When does it become horribly inefficient ? I have only 10-100 rows which come from this query - `EXEC xp_dirtree 'C:\Files', 10, 1 ` – Steam Mar 07 '14 at 02:35
  • 1
    @blasto - they certainly have their uses, but can cause perf related problems if abused. this answer is better than any way I could explain it: http://stackoverflow.com/a/747376/91619 – David Duffett Mar 07 '14 at 04:14
27

Use the following statement:

INSERT INTO EmployeePayroll
SELECT
  0,EmployeeID ,0,0,0
FROM
  Employees

You can check for the existance of the record before inserting it by appending:

WHERE
  ID NOT IN
  (
     SELECT
       EmployeeID
     FROM
       EmployeePayroll
  )
Akram Shahda
  • 14,655
  • 4
  • 45
  • 65
  • 1
    thanks my friend this code will fix current problem for sure , I ask Allah to save Syria ,but is can i used For each because i write a small example only just to make it easy but the real code is very long and there are more than 3 functions to be used inside that code . so is there For each loop in sql server or do i have to use Loop only? – HAJJAJ May 02 '11 at 11:41
  • @HAJJAJ: May Allah save Yemen too my friend. I suggest using [cursors](http://msdn.microsoft.com/en-us/library/ms180169.aspx) to loop on your rows. – Akram Shahda May 02 '11 at 12:14
5

This is the one way to achieve your requirement using While loop & Temp table variable,

The sample query is given below,

--: Get the Employees table data & insert this to temp table variable
Declare @TempEmpTbl Table (RowId int identity, EmployeeID int, EmployeeName nvarchar(100), EmployeeStatus int, BasicSalary int);
Insert into @TempEmpTbl Select * from Employees;

--: temp variables
Declare @TempEmpCount Int = (Select Count(RowId) From @TempEmpTbl);
Declare @MinCount Int = 1;
Declare @GetEmpId int;

--: while loop for EmployeePayroll tbl insertion based on Employees data
While(@TempEmpCount >= @MinCount)
Begin
    Set @GetEmpId = (Select EmployeeID From @TempEmpTbl Where RowId = @MinCount);   
    Insert into EmployeePayroll values (0, @GetEmpId,0 ,0 ,0)
    Set @MinCount = @MinCount + 1;
End

Note : Suppose the employee record is already there, we can able to update EmployeePayroll records from within this while loop.

Has AlTaiar
  • 4,052
  • 2
  • 36
  • 37
Manikandan Sethuraju
  • 2,873
  • 10
  • 29
  • 48
2
INSERT INTO EmployeePayroll
SELECT
 0,E.EmployeeID ,0,0,0
FROM
Employees E
WHERE 
NOT EXISTS
(
  SELECT
       1
     FROM
       EmployeePayroll WHERE EmployeeID = E.Id
)

Hope this helps

This is most optimized way to achieve this

Thangamani Palanisamy
  • 5,152
  • 4
  • 32
  • 39
0

I was looking for a decent way for a foreach loop in SQL and came up with this easy code

SELECT RowNum = ROW_NUMBER() OVER(ORDER BY Id),*
INTO #Locations
FROM [dbo].[Location]

DECLARE @MaxRownum INT
SET @MaxRownum = (SELECT MAX(RowNum) FROM #Locations)

DECLARE @Iter INT
SET @Iter = (SELECT MIN(RowNum) FROM #Locations)



WHILE @Iter <= @MaxRownum
BEGIN
DECLARE @currentCountry varchar(250)
DECLARE @locId int
SET @currentCountry = ( SELECT Country 
                        FROM #Locations
                        WHERE RowNum = @Iter)

SET @LocId = (  SELECT Id 
                FROM #Locations
                WHERE RowNum = @Iter)



    -- run your operation here
Update [dbo].[Location]
SET CountryId  = (SELECT (Id) FROM [dbo].[Site] WHERE [dbo].[Site].Name = @currentCountry)
WHERE [dbo].[Location].Id = @locId


    SET @Iter = @Iter + 1
END

DROP TABLE #Locations
Bishoy Hanna
  • 4,539
  • 1
  • 29
  • 31
0

Try Cross Apply. This is the best alternate for cursor and looping. Mover over if you compare the execution plan of cross apply with other methods you will notice its noticeably faster

http://sqlserverplanet.com/sql-2005/cross-apply-explained

Sarathi B
  • 49
  • 2
0

HI

USE Default constraints for the column which needs to be zero

payrollID,VoucherNo, BasicSalary, Salary-Month

insert the EmployeeID for the same and use the above mentioned concept