splitting a text list in sql
http://www.bigbold.com/snippets/posts/show/774
Often times I have a list of integers I need to pass to the database to get worked on. Such as checkboxes on a web page or some other list. I needed some TSQL that would take a text string and split it by a separator, in this case a comma. The following is the result of that need.
The way I normally use it is in a stored procedure like the one below with several text type arguments. This is a variation designed to split a list of strings separated by a special character sequence. Image two lists, one of the ids and one of the data. You parse the first list to get a table of the ids and you parse the second list to get the data and insert/update as appropriate.
http://www.bigbold.com/snippets/posts/show/774
1 2 IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[uspSplitTextList]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1) 3 DROP PROCEDURE [dbo].[uspSplitTextList] 4 GO 5 6 SET QUOTED_IDENTIFIER ON 7 GO 8 SET ANSI_NULLS ON 9 GO 10 11 12 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 13 -- uspSplitTextList 14 -- 15 -- Description: 16 -- splits a separated list of text items and returns the text items 17 -- 18 -- Arguments: 19 -- @list_text - list of text items 20 -- @Delimiter - delimiter 21 -- 22 -- Notes: 23 -- 02/22/2006 - WSR : use DATALENGTH instead of LEN throughout because LEN doesn't count trailing blanks 24 -- 25 -- History: 26 -- 02/22/2006 - WSR : revised algorithm to account for items crossing 8000 character boundary 27 -- 28 CREATE PROCEDURE uspSplitTextList 29 @list_text text, 30 @Delimiter varchar(3) 31 AS 32 33 SET NOCOUNT ON 34 35 DECLARE @InputLen integer -- input text length 36 DECLARE @TextPos integer -- current position within input text 37 DECLARE @Chunk varchar(8000) -- chunk within input text 38 DECLARE @ChunkPos integer -- current position within chunk 39 DECLARE @DelimPos integer -- position of delimiter 40 DECLARE @ChunkLen integer -- chunk length 41 DECLARE @DelimLen integer -- delimiter length 42 DECLARE @ItemBegPos integer -- item starting position in text 43 DECLARE @ItemOrder integer -- item order in list 44 DECLARE @DelimChar varchar(1) -- first character of delimiter (simple delimiter) 45 46 -- create table to hold list items 47 -- actually their positions because we may want to scrub this list eliminating bad entries before substring is applied 48 CREATE TABLE #list_items ( item_order integer, item_begpos integer, item_endpos integer ) 49 50 -- process list 51 IF @list_text IS NOT NULL 52 BEGIN 53 54 -- initialize 55 SET @InputLen = DATALENGTH(@list_text) 56 SET @TextPos = 1 57 SET @DelimChar = SUBSTRING(@Delimiter, 1, 1) 58 SET @DelimLen = DATALENGTH(@Delimiter) 59 SET @ItemBegPos = 1 60 SET @ItemOrder = 1 61 SET @ChunkLen = 1 62 63 -- cycle through input processing chunks 64 WHILE @TextPos <= @InputLen AND @ChunkLen <> 0 65 BEGIN 66 67 -- get current chunk 68 SET @Chunk = SUBSTRING(@list_text, @TextPos, 8000) 69 70 -- setup initial variable values 71 SET @ChunkPos = 1 72 SET @ChunkLen = DATALENGTH(@Chunk) 73 SET @DelimPos = CHARINDEX(@DelimChar, @Chunk, @ChunkPos) 74 75 -- loop over the chunk, until the last delimiter 76 WHILE @ChunkPos <= @ChunkLen AND @DelimPos <> 0 77 BEGIN 78 79 -- see if this is a full delimiter 80 IF SUBSTRING(@list_text, (@TextPos + @DelimPos - 1), @DelimLen) = @Delimiter 81 BEGIN 82 83 -- insert position 84 INSERT INTO #list_items (item_order, item_begpos, item_endpos) 85 VALUES (@ItemOrder, @ItemBegPos, (@TextPos + @DelimPos - 1) - 1) 86 87 -- adjust positions 88 SET @ItemOrder = @ItemOrder + 1 89 SET @ItemBegPos = (@TextPos + @DelimPos - 1) + @DelimLen 90 SET @ChunkPos = @DelimPos + @DelimLen 91 92 END 93 ELSE 94 BEGIN 95 96 -- adjust positions 97 SET @ChunkPos = @DelimPos + 1 98 99 END 100 101 -- find next delimiter 102 SET @DelimPos = CHARINDEX(@DelimChar, @Chunk, @ChunkPos) 103 104 END 105 106 -- adjust positions 107 SET @TextPos = @TextPos + @ChunkLen 108 109 END 110 111 -- handle last item 112 IF @ItemBegPos <= @InputLen 113 BEGIN 114 115 -- insert position 116 INSERT INTO #list_items (item_order, item_begpos, item_endpos) 117 VALUES (@ItemOrder, @ItemBegPos, @InputLen) 118 119 END 120 121 -- delete the bad items 122 DELETE FROM #list_items 123 WHERE item_endpos < item_begpos 124 125 -- return list items 126 SELECT SUBSTRING(@list_text, item_begpos, (item_endpos - item_begpos + 1)) AS item_text, item_order, item_begpos, item_endpos 127 FROM #list_items 128 ORDER BY item_order 129 130 END 131 132 DROP TABLE #list_items 133 134 RETURN 135 136 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ 137 138 GO 139 SET QUOTED_IDENTIFIER OFF 140 GO 141 SET ANSI_NULLS ON 142 GO