スペースで区切られた任意の数の単語を含むことができる文字列があります。この文字列をパラメーターとして vb から sqlCommand 経由で sql に送信しています。これをsqlの配列に分割するか、vbから配列として送信してテーブルを検索するにはどうすればよいですか。
SQL 検索は、渡された文字列のすべての単語が各行に含まれているすべての行を返す必要があります。
テーブル パラメーターを使用する以外に、文字列を解析してテーブル変数にすることができます。疑似コードは次のようになります。
Declare a table variable with one VARCHAR column
While the string is not empty
Grab everything up to the first space and insert it into the table variable
Remove the first word from the string
一時テーブルを取得したら、LIKE を使用してソース テーブルと結合できます。ソース テーブルの行ごとに、配列内で一致したすべての単語の行が結合によって作成されます。次に、GROUP/HAVING を使用して、テーブル変数の各エントリの行を返した結果 (テーブル変数のすべての文字列に一致するもの) のみに制限できます。
例えば:
DECLARE @TempTable TABLE (Word VARCHAR(100))
...
-- Put logic from the pseudocode above to populate @TempTable from your string
...
SELECT Y.PrimaryKey, MAX(Y.MaybeYouNeedThisColumnToo) from YourTable Y
INNER JOIN @TempTable temp
ON Y.ColumnToMatch LIKE '%' + temp.Word + '%'
GROUP BY Y.PrimaryKey
HAVING COUNT(*) = (SELECT COUNT(*) FROM @TempTable)
Using connection As New SqlConnection(connectionString)
Dim command As New SqlCommand("sp_GetCustomerByIDS", connection)
command.CommandType = System.Data.CommandType.StoredProcedure
'Here is how you pass in YourString seperated with comma's
command.Parameters.AddWithValue("@CustomerIDS", YourString.Replace(" ", ","))
...
End Using
コンマ区切りの値の文字列がストアド プロシージャに渡されます (ヒント: SQL2005/SQL2008+ にはvarchar(MAX)があるため、 ntextを変更してください)。
CREATE PROCEDURE [dbo].[sp_GetCustomerByIDS]
@CustomerIDS ntext
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @err int
declare @TempTbl as TABLE(mystrings nvarchar(32), i1 int, i2 int, i3 int)
INSERT @TempTbl exec @err = sp_SplitTextList @CustomerIDS, ','
SELECT *
FROM dbo.Customers
WHERE
dbo.Customers.ID in (select mystrings from @TempTbl)
END
この SplitTextList ストアド プロシージャを使用して、カンマ区切りの値を処理します。ここでも、@list_text をテキストから varchar(MAX) に変更することができます。履歴から、かなり古いことがわかります。
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-- uspSplitTextList
--
-- Description:
-- splits a separated list of text items and returns the text items
--
-- Arguments:
-- @list_text - list of text items
-- @Delimiter - delimiter
--
-- Notes:
-- 02/22/2006 - WSR : use DATALENGTH instead of LEN throughout because LEN doesn't count trailing blanks
--
-- History:
-- 02/22/2006 - WSR : revised algorithm to account for items crossing 8000 character boundary
--
CREATE PROCEDURE [dbo].[sp_SplitTextList]
@list_text text,
@Delimiter varchar(3)
AS
SET NOCOUNT ON
DECLARE @InputLen integer -- input text length
DECLARE @TextPos integer -- current position within input text
DECLARE @Chunk varchar(8000) -- chunk within input text
DECLARE @ChunkPos integer -- current position within chunk
DECLARE @DelimPos integer -- position of delimiter
DECLARE @ChunkLen integer -- chunk length
DECLARE @DelimLen integer -- delimiter length
DECLARE @ItemBegPos integer -- item starting position in text
DECLARE @ItemOrder integer -- item order in list
DECLARE @DelimChar varchar(1) -- first character of delimiter (simple delimiter)
-- create table to hold list items
-- actually their positions because we may want to scrub this list eliminating bad entries before substring is applied
CREATE TABLE #list_items ( item_order integer, item_begpos integer, item_endpos integer )
-- process list
IF @list_text IS NOT NULL
BEGIN
-- initialize
SET @InputLen = DATALENGTH(@list_text)
SET @TextPos = 1
SET @DelimChar = SUBSTRING(@Delimiter, 1, 1)
SET @DelimLen = DATALENGTH(@Delimiter)
SET @ItemBegPos = 1
SET @ItemOrder = 1
SET @ChunkLen = 1
-- cycle through input processing chunks
WHILE @TextPos <= @InputLen AND @ChunkLen <> 0
BEGIN
-- get current chunk
SET @Chunk = SUBSTRING(@list_text, @TextPos, 8000)
-- setup initial variable values
SET @ChunkPos = 1
SET @ChunkLen = DATALENGTH(@Chunk)
SET @DelimPos = CHARINDEX(@DelimChar, @Chunk, @ChunkPos)
-- loop over the chunk, until the last delimiter
WHILE @ChunkPos <= @ChunkLen AND @DelimPos <> 0
BEGIN
-- see if this is a full delimiter
IF SUBSTRING(@list_text, (@TextPos + @DelimPos - 1), @DelimLen) = @Delimiter
BEGIN
-- insert position
INSERT INTO #list_items (item_order, item_begpos, item_endpos)
VALUES (@ItemOrder, @ItemBegPos, (@TextPos + @DelimPos - 1) - 1)
-- adjust positions
SET @ItemOrder = @ItemOrder + 1
SET @ItemBegPos = (@TextPos + @DelimPos - 1) + @DelimLen
SET @ChunkPos = @DelimPos + @DelimLen
END
ELSE
BEGIN
-- adjust positions
SET @ChunkPos = @DelimPos + 1
END
-- find next delimiter
SET @DelimPos = CHARINDEX(@DelimChar, @Chunk, @ChunkPos)
END
-- adjust positions
SET @TextPos = @TextPos + @ChunkLen
END
-- handle last item
IF @ItemBegPos <= @InputLen
BEGIN
-- insert position
INSERT INTO #list_items (item_order, item_begpos, item_endpos)
VALUES (@ItemOrder, @ItemBegPos, @InputLen)
END
-- delete the bad items
DELETE FROM #list_items
WHERE item_endpos < item_begpos
-- return list items
SELECT SUBSTRING(@list_text, item_begpos, (item_endpos - item_begpos + 1)) AS item_text, item_order, item_begpos, item_endpos
FROM #list_items
ORDER BY item_order
END
DROP TABLE #list_items
RETURN