操作Microsoft SQL Server数据库批量处理大量数据时,为了提高效率都会想到使用存储过程。今天写了一段程序是实现批量更新用户信息的功能,便设计了一个存储过程,传入用户GUID和其它信息,存储过程批量更新所指定用户数据。
传入的用户GUID可能是1个也可能是几个,存储过程中的有几处where子句使用了in (@userguid),一般在程序代码中写SQL语句时各个字符串都需要一对单引号括起来,形如:in ('06e14218-e621-42b9-98aa-1cda94aa06f4','236c30bb-bc9f-4069-a1b3-ead399604ac1')。但传递给存储过程时则不能带单引号了,会报转换格式错误。
但今天要说的问题不在这里,存储过程的where子句如果写成in (@userguid),即使传给userguid参数的值是不带单引号的值:06e14218-e621-42b9-98aa-1cda94aa06f4,236c30bb-bc9f-4069-a1b3-ead399604ac1,存储过程能完全执行,但只有第一个用户GUID的数据更新了,其它的都没有。这就是问题所在了。
根据网上的介绍和个人经验,对网上介绍的表值函数fn_Split做了简单的优化,以使其更实用,解决存储过程中需要把参数字符串值分割的处理。fn_Split代码如下:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ====================================================
-- Author: SeaYee
-- Create date: 2011-06-14
-- Description: MS SQL实现类似C# split功能的表值函数
-- ====================================================
CREATE FUNCTION [dbo].[fn_Split]
(
@str VARCHAR(MAX), -- 待处理的字符串
@sep VARCHAR(10) -- 分隔字符
)
RETURNS @arr TABLE
(
[value] VARCHAR(100)
)
AS
BEGIN
DECLARE @i INT, @tmpStr VARCHAR(100)
SET @i = CHARINDEX(@sep, @str)
WHILE @i > 0
BEGIN
SET @tmpStr = SUBSTRING(@str, 1, @i-1)
SET @str = STUFF(@str, 1, @i, '')
SET @i = CHARINDEX(@sep, @str)
INSERT INTO @arr([value]) VALUES(@tmpStr)
END
INSERT INTO @arr([value]) VALUES(@str)
RETURN
END
GO
就以上面的代码为例,只要把存储过程中where子句使用了in (@userguid)的改成in (select * from dbo.fn_Split(@UserGuid, ',')),问题就解决了。