我有一个存储过程,只需点击一下按钮就可以输入超过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 :(得分: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
声明中有三个重大错误:
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()) )