现有表数据如下:
AA BB
1 我
2 爱
3 中
4 学
5 大
6 国
7 人
需求:书写函数,当传递的参数形式如:1,2,3,6,时
输出:我,爱,中,国
这个问题困扰了我很久,一直没能实现。主要时因为必须写成函数:
我的思路时将参数解析成('1','2','3','4'),然后用in关键字进行查询。
但是,始终无法在IN后面把解析出来的值加上去。
然而,换种思路拼凑SQL字符串,通过sp_executesql 来执行,却又无法返回值。
(ps可能是我菜,一直没能通过sp_executesql实现给变量赋值)
现经高人指点,整一通用方法,有点复杂但是百试百灵,嘿嘿:
思路:SQL中想实现上面类型的参数最好时先将参数解析成数组,再将解析出来的数组传递给函数获取值。
函数1:
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
GO
/*
时间:2009-6-16
编写人:lop_xiaobo
功能:切割字符串,并返回生成的数据
select SplitTextToStringArray('53dab246-f635-4a88-93e5-
c2f2a871f9a7,03a22c38-272a-44c4-88a4-75d46aaf536a')
*/
ALTER FUNCTION [dbo].[SplitTextToStringArray]
(
@text varchar(8000),
@delimiter char(1)
)
RETURNS @arrayTable TABLE(Idx bigint, [Value] nvarchar(200))
AS
BEGIN
DECLARE @splitlen int
SET @splitlen = 4000
DECLARE @Idx int SET @Idx = 0
-- 定义取子串的起始位置
DECLARE @textsplit bigint
SET @textsplit = 1
WHILE( @textsplit <= DATALENGTH(@text) )
BEGIN
-- 由于许多字符串处理函数无法用于ntext数据类型
-- 所以需要循环按批处理ntext字符串,一批取出
-- 个字符放入nvarchar(4000)类型的变量中.
DECLARE @string nvarchar(4000)
SELECT @string = SUBSTRING(@text,@textsplit,@splitlen)
-- 能够取出满个字符
IF LEN(@string) = @splitlen
BEGIN
-- 确保取出的个字符是完整的由分隔符隔开的字符串组合
DECLARE @lastcomma int
SELECT @lastcomma = CHARINDEX(@delimiter,REVERSE
(@string),1)
-- 最后一个分隔符后面的字符串不完整,应抛弃
IF @lastcomma > 0
BEGIN
SELECT @string = SUBSTRING(@string,1,@splitlen -
@lastcomma)
-- 设置下一次从@text取字符的起始位置
SELECT @textsplit = @textsplit + @splitlen - @lastcomma
+ 1
END
-- 最后一个分隔符后面的字符串完整.
ELSE
BEGIN
SELECT @textsplit = @textsplit + @splitlen + 1
END
END
-- 取出不满个字符
ELSE
BEGIN
SELECT @textsplit = @textsplit + @splitlen + 1
END
-- 解析@string,取出以分隔符为界限的子字符串
DECLARE @i1 int SET @i1 = 1
DECLARE @i2 int SET @i2 = 1
WHILE @i1 <= LEN(@string)
BEGIN
SET @i2 = CHARINDEX(@delimiter,@string,@i1+1)
IF @i2 = 0
SET @i2 = LEN(@string) + 1
INSERT @arrayTable (Idx, Value)
SELECT @Idx, SUBSTRING(@string,@i1,@i2-@i1)
SET @i1 = @i2 + 1
SET @Idx = @Idx + 1
END
END
RETURN
END
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
-
函数2:
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
/*
时间:2009-6-16
编写人:lop_xiaobo
功能:根据条件累加相关字段成字符串
select uf_GroupNameOfUser('53dab246-f635-4a88-93e5-c2f2a871f9a7,03a22c38-272a-44c4-88a4-75d46aaf536a')
*/
ALTER function uf_GroupNameOfUser
(
@userlist varchar(4000)
)
returns varchar(4000)
as
begin
declare @deptlist varchar(4000),@str varchar(50)
select @deptlist= ''
DECLARE @stringArrayT TABLE(Idx bigint, [Value] nvarchar(200))
--解析传递的参数并放入数据
INSERT INTO @stringArrayT(Idx, [Value])
(
SELECT Idx, [Value]
FROM SplitTextToStringArray(@userlist, ',') )
--通过游标实现字符串的累加
declare cs_userdeptlist Cursor
for
--这里书写查询语句,得到要累加的字段
select distinct deptid from dbo.p_dept_member where userid in
(
select n_id from dbo.p_user_info where c_Login_name in(select [Value] from @stringArrayT)
)
Open cs_userdeptlist
Fetch next From cs_userdeptlist into @str
WHILE @@FETCH_STATUS = 0
BEGIN
select @deptlist= @str + ',' + @deptlist --累加
Fetch next From cs_userdeptlist into @str
end
close cs_userdeptlist
deallocate cs_userdeptlist
if len(@deptlist) > 1
select @deptlist = substring(@deptlist,1,len(@deptlist)-1)
return @deptlist
end
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
-
函数:SplitTextToStringArray 将参数解析生成数组.
函数:uf_GroupNameOfUser 供用户调用,获取值.
-
这两个函数很方便修改,解析函数不用修改,只要修改你要查询的语句就行,也就是修改游标里的内容就可以了.