如何在存储过程中通过数组进行搜索?

问题描述 投票:0回答:3

我有一个字符串,可以包含任意数量的由空格分隔的单词。我通过 sqlCommand 将此字符串作为参数从 vb 发送到 sql。我如何将其拆分为sql中的数组或将其作为数组从vb完全发送以搜索表。

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

sql vb.net
3个回答
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
投票

创建函数 [dbo].[SplitString]
(
@String NVARCHAR(MAX)
)
返回@OutputTable 表
(
[值] NVARCHAR(MAX)
)
AS
开始
声明@Value NVARCHAR(MAX)
声明@Pos INT
声明 @Piece NVARCHAR(MAX)

SET @String = LTRIM(RTRIM(@String)) + ' '  
SET @Pos = CHARINDEX(' ', @String, 1)  

WHILE @Pos > 0  
BEGIN  
    SET @Piece = LTRIM(RTRIM(LEFT(@String, @Pos - 1)))  
    IF @Piece <> ''  
    BEGIN  
        INSERT INTO @OutputTable ([Value])  
        VALUES (@Piece)  
    END  
    SET @String = RIGHT(@String, LEN(@String) - @Pos)  
    SET @Pos = CHARINDEX(' ', @String, 1)  
END  

RETURN  

结束

要在 SQL 中将字符串拆分为数组,您可以创建一个像上面那样的用户定义函数。该函数接受一个字符串作为输入并返回一个表,其中每个单词作为单独的行。

  1. 函数 SplitString 将字符串 @String 作为输入。
  2. 它初始化用于处理字符串的变量。
  3. 它会修剪输入字符串并附加一个空格以进行一致处理。
  4. 它迭代字符串,找到用空格分隔的每个单词。
  5. 如果@OutputTable不为空,则将每个单词插入到其中。
  6. 该函数返回包含单个单词的表格。 要在 SQL 查询中使用此函数来搜索包含输入字符串中所有单词的行,您可以将字符串从 VB.NET 传递到 SQL,并利用 split 函数根据每个单词进行高效搜索。

-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存储过程来处理逗号分隔值,您可能想将@list_text从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
© www.soinside.com 2019 - 2024. All rights reserved.