-1

Ok, first question, and you guys scare me with how much you know, so please be gentle...

I am trying to pass in a delimited string and convert it to an array in a stored procedure and then use the array to check against values in a column. Here's the catch. I'm trying to take the preexisting table, that checks for one association and expand it to allow for multiple associations.

So the column annAssociations might have three ids, 4,16,32, but I need to check if it belongs to the groupIds being queried, 6,12,32. Since one of the values matched, it should return that row.

Here is the procedure as it exists.

CREATE PROCEDURE [dbo].[sp_annList] 
-- Date Range of Announcements.
@dateBegin datetime,
@dateEnd datetime,
    -- Announcement type and associations.
@annType varchar(50),
@annAssociation varchar(255)

AS
BEGIN

-- Set the SELECT statement for the announcements.
SET NOCOUNT ON;
-- See if this should be a limited query
IF @annAssociation <> ''
    Begin
        SELECT * 
        FROM announcements
        WHERE (date1 <= @dateEnd AND date2 >= @dateBegin) -- See if the announcement falls in the date range.
            AND annType = @annType -- See if the announcement is the right type.
            AND annAssociations LIKE (select SplitText from dbo.fnSplit(@annAssociation, ','))
        ORDER BY title
    END
Else 
    Begin
        SELECT *
        FROM announcements
        WHERE (date1 <= @dateEnd AND date2 >= @dateBegin)
            AND annType = @annType
        ORDER BY title
    End
END

And here is the method I'm using to convert the delimited string and store it in a temporary table.

CREATE Function [dbo].[fnSplit](@text text, @delimitor nchar(1))

RETURNS
@table TABLE
(
[Index] int Identity(0,1),
[SplitText] varchar(10)
)
AS

BEGIN
declare @current varchar(10)
declare @endIndex int
declare @textlength int
declare @startIndex int

set @startIndex = 1

if(@text is not null)
begin
    set @textLength = datalength(@text)

    while(1=1)
    begin
        set @endIndex = charindex(@delimitor, @text, @startIndex)

        if(@endIndex != 0)
        begin
            set @current = substring(@text,@startIndex, @endIndex - @StartIndex)
            Insert Into @table ([SplitText]) values(@current)
            set @startIndex = @endIndex + 1   
        end
        else
        begin
            set @current = substring(@text, @startIndex, datalength(@text)-@startIndex+1)
            Insert Into @table ([SplitText]) values(@current)
            break
        end
    end

end

return
END

Sorry for the long question. I just wanted to get all the info out there. I've been researching for days, and I either don't know where to look or am missing something obvious.

4

1 回答 1

0

您可能不会获得比这种方法更好的性能(您可能会看到使用 CLR 拆分函数获得更好的性能,但在 3 或 4 项时您不会看到太大差异):

SELECT * 
  FROM announcements AS a
  WHERE ...
  AND EXISTS (SELECT 1 FROM dbo.fnSplit(@annAssociation) AS n
    WHERE ',' + a.annList + ',' LIKE '%,' + n.SplitText + ',%');

这里的关键是您只需要拆分其中一个列表。

真的应该停止在annAssocations列中存储多个值。每个 id 都是一个单独的数据,应该单独存储(除了更好地符合规范化之外,它还会使这样的查询更简单)。

于 2012-06-12T00:24:12.030 回答