The need for splitting is giving me worse performance for my SP's than dynamic SQL. It's making me think long and hard about converting everything to SP's. I've tried both of the following split functions (with the unlim function needing a Numbers table but strangely having less that 1/3 the plan cost of the non-unlim one). They are both far slower than just a dynamic SQL (SQL3) though but I have no other good way to pass a list of values to an SP.-- SQL1 Cost .0625 (22%)delete externalgraderesults from externalgraderesults r join dbo.udf_SplitUnlim(@externalresultIdList,',') idlist on r.externalgraderesult_id=idlist.value-- SQL2 Cost .207 (73.25%) delete externalgraderesults from externalgraderesults r join dbo.udf_Split(@externalresultIdList,',') idlist on r.externalgraderesult_id=idlist.value-- SQL3 Cost .0133 (4.7%) delete from externalgraderesults where externalgraderesult_id in (18,122,131)
-- 7998 bytes max (but faster) CREATE FUNCTION dbo.udf_Split (@param varchar(7998)) RETURNS TABLE AS RETURN(SELECT substring(',' + @param + ',', Number + 1, charindex(',', ',' + @param + ',', Number + 1) - Number - 1) AS Value FROM Numbers WHERE Number <= len(',' + @param + ',') - 1 AND substring(',' + @param + ',', Number, 1) = ',') -- Unlimited size CREATE FUNCTION dbo.udf_SplitUnlim(@list ntext, @delim nchar(1) = N',') RETURNS @t TABLE (str varchar(4000), nstr nvarchar(2000)) AS BEGIN DECLARE @slices TABLE (slice nvarchar(4000) NOT NULL) DECLARE @slice nvarchar(4000), @textpos int, @maxlen int, @stoppos int SELECT @textpos = 1, @maxlen = 4000 - 2 WHILE datalength(@list) / 2 - (@textpos - 1) >= @maxlen BEGIN SELECT @slice = substring(@list, @textpos, @maxlen) SELECT @stoppos = @maxlen - charindex(@delim, reverse(@slice)) INSERT @slices (slice) VALUES (@delim + left(@slice, @stoppos) + @delim) SELECT @textpos = @textpos - 1 + @stoppos + 2 -- On the other side of the comma. END INSERT @slices (slice) VALUES (@delim + substring(@list, @textpos, @maxlen) + @delim) INSERT @t (str, nstr) SELECT str, str FROM (SELECT str = ltrim(rtrim(substring(s.slice, N.Number + 1, charindex(@delim, s.slice, N.Number + 1) - N.Number - 1))) FROM Numbers N JOIN @slices s ON N.Number <= len(s.slice) - 1 AND substring(s.slice, N.Number, 1) = @delim) AS x RETURN END