0

我有一个用 C# 开发的 Web 应用程序,其中一个页面显示 SQL 查询的输出;查询是对存储过程的 linq 调用,我使用的是 SQL Server 2008。

其中一列显示与结果行关联的标签;在同一页面上显示复选框列表,每个复选框对应一个标签,如果用户打开或关闭一个或多个复选框,我想过滤查询。

我最简单的 SQL 解决方案对我们来说是“NOT IN”,如下所示:

select * from [mytable] where [tags] not in ('tag1','tag2, etc...)

鉴于我将 FORM POST 转换为带有逗号分隔值的字符串。例子:

string tags = ParseFormAndConvertCheckBoxToCSV(Page.Request.Form);
string sqlcmd = "select * from [mytable] where [tags] not in (" + tags + ")";

但我不想动态构建 SQL,因为据我所知那会很糟糕

我可以想象几种在 SQL 中用逗号分隔的值列表拆分字符串并将值存储到内存表中的方法:

declare @tagscsv nvarchar(MAX)
declare @notags TABLE(Value nvarchar(50))

set @tagscsv = 'taxi,ivf'

Declare @x XML 
select @x = cast('<A>'+ replace(@tagscsv,',','</A><A>')+ '</A>' as xml)

insert into @notags
select t.value('.', 'nvarchar(50)') as v from @x.nodes('/A') as x(t)

select * from [mytable] where [tags] not in (select * from @notags)

...但这听起来也像是一个肮脏的把戏。

对我来说,这看起来应该是一个非常普遍的情况,我发现很多人过去都面临过这个问题,但是在谷歌上搜索我找不到一个优雅的解决方案。

任何人都可以帮忙吗?

4

1 回答 1

1

编辑:错过了存储过程部分。使用存储过程,您没有很多选择。我通常会做你所做的,拆分逗号分隔的字符串并将值保存到临时表(或表变量)中。

CREATE PROCEDURE SplitAndStuff
    @List nvarchar(MAX) = NULL,
    @SplitOn nvarchar(5) = ','  --This can be replaced with a literal if it is always a comma.
AS
BEGIN
    DECLARE @Pos int;
    DECLARE @SplitOnLength int;
    DECLARE @Results TABLE (value nvarchar(MAX))
    SET @SplitOnLength = DATALENGTH(@SplitOn) / 2;

    IF (RIGHT(@List, @SplitOnLength) <> @SplitOn) SET @List = @List + @SplitOn; --Add trailling split string if there is not one already.

    SET @Pos = CHARINDEX(@SplitOn, @List, 1)                                    --Initalize for loop.  (The starting position returned is 1-based, not 0-based.)

    WHILE @Pos > 0
    BEGIN
        INSERT INTO @Results (value) SELECT CAST(SUBSTRING(@List,1,@Pos-1)AS int);

        SET @List = SUBSTRING(@List, @Pos+@SplitOnLength, DATALENGTH(@List) / 2);
        SET @Pos = CHARINDEX(@SplitOn, @List, 1);
    END
END
GO

如果您的存储过程没有做任何其他事情(除了查找),您可以在下面使用我原来的 LINQ 答案:

由于您使用的是 LINQ,因此您需要拆分tagscsv并使用结果数组来执行“在哪里”查询:

string[] tags = tagscsv.Split(',');
var output = from q in db.Table where !tags.Contains(q) select q;

也可以看看:

于 2012-04-27T19:05:59.890 回答