1

従業員の毎日の出席を閉じるために使用されるワンボタンクリックで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
   }
}

ストアドプロシージャでデータテーブルをループするためのより良い解決策を誰かが提案できますか?

4

1 に答える 1

5

SQL Server 2008 を使用しているため、これはまさにMERGEステートメントを使用するためのシナリオです。ループなどは必要ありません - 1 つの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ステートメントは 1 回実行され、すべての作業が 1 回のパスで実行されます。ループも RBAR (行ごとのアゴナイジング) 処理もありません。そのようなことはありません。セットベースの優れた高速ステートメントを 1 つ作成すれば、完了です。

更新:あなたの更新された質問から、あなたの声明には3 つの大きな誤りがあることがわかります。MERGE

 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()) )
于 2012-12-09T08:53:47.800 に答える