2012-12-09 22 views
0

我有一個存儲過程,必須在單擊按鈕時輸入超過8000行,用於關閉員工的日常出勤。在存儲過程中循環數據表

我打算在輸入發送到存儲過程作爲數據表,而不是按行每次發送它作爲行

我成功地創建一個表類型的用戶定義的類型和使用與該用戶定義類型的參數作爲輸入參數

USE [ATCHRM.MDF] 
GO 

/****** Object: UserDefinedTableType [dbo].[employeeswipedclose123] Script Date: 12/11/2012 12:04:34 ******/ 
CREATE TYPE [dbo].[employeeswipedclose123] AS TABLE(
    [empid] [int] NULL, 
    [datetoday] [datetime] NULL, 
    [Swipepk] [int] NULL 
) 
GO 
    CREATE PROCEDURE dbo.CloseAttendance (@closingemployee dbo.employeeswipedclose123 READONLY) 
AS 
BEGIN 

    MERGE EmployeSwipeDaily_tbl AS Target 

    USING @closingemployee AS Source 

    ON (Target.empid = Source.empid) and (Target.Date = Source.datetoday) 

    WHEN MATCHED THEN 
     BEGIN 
      UPDATE Target 
      SET Target. IsCompleted = N'Y' 
      WHERE  (Source.swipePK = Target.Swipepk) AND (Source.empid = Target.empid) AND (Target.Date = Source.datetoday) 

     WHEN NOT MATCHED THEN 

     INSERT INTO Target 
     (empid, Swipin, SwipeOut, Date, Duration, deviceid, InStatus, Outstatus, Invalue, OutValue, IsCompleted, CompletedDate) 
     VALUES  (@empid, CONVERT(DATETIME, ' 00:00:00', 102), CONVERT(DATETIME, ' 00:00:00', 102),@datetoday, CONVERT(DATETIME, 
         ' 00:00:00', 102), 0, N'A', N'A', 0, 0, N'Y',(select GETDATE())) 

END 


GO 

但現在我想什麼是存儲過程裏面我想環路Datatable和檢查條件

如這樣

for(int i=0 ;i<dt.count;i++) 
{ 
    if(dt.rows[i][swipepk]==0) 
    { 
     insert into employe swipe tbl() 
    } 
    else 
    { 
     update employee tbl 
    } 
} 

任何人都可以提出一個更好的解決方案來循環存儲過程中的數據表?

+0

能否請您解釋一下什麼是你想與表'中的數據做dbo.Employeedata'?你在試圖合併數據嗎?相反,可能有一個簡單的解決方案。 –

+0

由於你在SQL Server 2008上 - 使用MERGE語句! **完全** MERGE'語句的場景 - 插入新行並更新現有的行... –

+0

employe表只是一個輸入參數....當用戶給一個按鈕單擊時...數據從一個網格視圖被捕獲並通過@closingemployee傳遞給存儲過程..... –

回答

5

由於您使用的是SQL Server 2008-這就是恰恰是使用MERGE語句的場景!沒有循環或任何需要 - 只需要一個MERGE聲明!

CREATE PROCEDURE dbo.CloseAttendance (@closingemployee dbo.Employeedata READONLY) 
BEGIN 
    -- this is the target of your MERGE - where the data is supposed to go 
    MERGE dbo.Employees AS Target 
    -- this is the source where the data to be merged comes from 
    USING @closingemployee AS Source 
    -- set up a "join" condition for those two sets of data 
    ON Target.empid = Source.empid 
    -- now define what to do when that JOIN condition matches 
    WHEN MATCHED THEN 
     UPDATE 
      SET Target.SomeColumn = Source.Swipepk --- or WHATEVER you need to update here! 
    -- now define what to do when that JOIN condition DOES NOT match (e.g. new employee) 
    WHEN NOT MATCHED THEN 
     INSERT(EmpId, CategoryName, Swipepk) 
     VALUES(Source.EmpId, Source.CategoryName, Source.Swipepk) ; 
END 

當然,您也可以做其他事情 - 如果需要,您可以定義更多匹配/不匹配條件。

這個MERGE語句只運行一次,並且在一次傳遞中完成所有工作 - 沒有循環,沒有RBAR(逐行激動 - 行)處理 - 沒有那種類型。一個好的,快速的,基於集合的陳述,你完成了!

更新:從更新的問題,我看你有沒有在你的MERGE聲明3個大誤區:

WHEN MATCHED THEN 
    BEGIN         <=== ERROR #1 : you CANNOT have a BEGIN here! 
     UPDATE Target 
     SET Target.IsCompleted = N'Y' 
     WHERE (Source.swipePK = Target.Swipepk) <=== ERROR #2 : you CANNOT have 
      AND (Source.empid = Target.empid)      additional WHERE 
      AND (Target.Date = Source.datetoday)     clause on the UPDATE 

WHEN NOT MATCHED THEN 
    INSERT INTO Target    <=== ERROR #3: you CANNOT define a INSERT INTO .... 
             the "INTO" table is already a given by the MERGE 
    (empid, Swipin, SwipeOut, Date, Duration, deviceid, InStatus, Outstatus, Invalue, OutValue, IsCompleted, CompletedDate) 
    VALUES  (@empid, CONVERT(DATETIME, ' 00:00:00', 102), CONVERT(DATETIME, ' 00:00:00', 102),@datetoday, CONVERT(DATETIME, 
        ' 00:00:00', 102), 0, N'A', N'A', 0, 0, N'Y',(select GETDATE())) 
+0

ON Target.empid = Source.empid ...我將在該目標表上有prevois天數據,所以總是employeeid將是在那裏,這種情況將永遠是真的,我可以把一個更多的條件,如Target.empid = Source.empid和Target.date = Source.date –

+0

@sreenathsreenath:你可以把**任何**條件在這裏 - 它只是有去es在源數據和目標數據之間建立一個JOIN –

+0

感謝marc讓我現在檢查 –