2013-06-21 111 views
2

我有一个字符串,可以包含任何数量的空格分隔的单词。我通过sqlCommand将这个字符串作为参数从vb发送到sql。我怎样才能把它分解成一个数组在sql中或者将它作为数组从vb中一起发送来搜索表。如何通过存储过程中的数组进行搜索?

sql搜索必须返回所有那些行中的每一行都包含我传递的字符串中的所有单词。

+0

表中的单词是如何存储的?这些词是否分类? –

+0

不,这些词没有排序 –

+1

如果您使用的是SQL Server 2008,请尝试使用表值参数http://msdn.microsoft.com/en-us/library/bb510489.aspx –

回答

-1
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 

值的逗号分隔的字符串被传递到存储过程(提示:请改变NTEXT作为SQL2005/SQL2008 +有VARCHAR(MAX)) :

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存储过程来处理逗号分隔值s,再次您可能需要将@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 
+0

我错过了什么吗?你从哪里得到表格的模式? “sql搜索必须返回所有这些行中的每一行都包含我通过的字符串中的所有单词”。 IN声明不符合OP提出的要求。根据OP表有一个字符串列,用空格隔开单词。该列应该包含通过参数传递的所有单词。 –

+0

@AlexS我对这个答案感觉不好,它来自9年前我写的代码。当我得到时间时,我会解决并添加表变量方法。希望Evan M能够在此期间添加它。 –

0

除了使用表参数外,还可以将字符串解析为表变量。这就是伪代码会是这样的:

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) 
+0

您可以使用示例来解释吗? –

+0

如果您可以通过没有伪代码的复制粘贴示例来显示它,这将会很有帮助。 –