Sql 如何使用来自HTTP表单的值列表执行类似于“notin”的WHERE?

Sql 如何使用来自HTTP表单的值列表执行类似于“notin”的WHERE?,sql,sql-server,forms,Sql,Sql Server,Forms,我用C语言开发了一个web应用程序,其中一个页面显示SQL查询的输出;该查询是对存储过程的linq调用,我使用的是SQL Server 2008 其中一列显示与结果行关联的标记;在同一页面上,将显示一个复选框列表,每个复选框对应一个标记,如果用户打开或关闭一个或多个复选框,我将过滤查询 我最简单的SQL解决方案对我们来说不是如下所示: select * from [mytable] where [tags] not in ('tag1','tag2, etc...) 给定条件,我将表单POST

我用C语言开发了一个web应用程序,其中一个页面显示SQL查询的输出;该查询是对存储过程的linq调用,我使用的是SQL Server 2008

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

我最简单的SQL解决方案对我们来说不是如下所示:

select * from [mytable] where [tags] not in ('tag1','tag2, etc...)
给定条件,我将表单POST转换为具有逗号分隔值的字符串。 例如:

但我不想动态构建SQL,因为据我所知

我几乎无法想象:

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

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

有人可以帮忙吗?

编辑:错过了存储过程部分。 对于存储过程,您没有很多选择。我通常会像您那样,拆分逗号分隔的字符串,并将值保存到临时表或表变量中

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
另见:


tags='A'或tags='B'等等,这就是您要寻找的吗?我不想动态构建SQL是什么意思,因为那样做很糟糕??试试我的解决方案[在这个问题上][1]。你说得对,这是一个很常见的问题。[1] :请提供其他上下文。您使用的是字符串SQL查询、linq到SQL还是其他?网页是建立在什么平台上的ASP、APSX、MVC、PHP等?还有,是什么让分隔逗号分隔的列表成为一个肮脏的把戏呢?我编辑了这个问题以提供更多的上下文,是的,我正在使用C、linq to实体和SQL server 2008的存储过程;但我觉得我的问题是一般性的,也适用于其他编程框架和数据库。要拆分字符串,我认为我发现的使用xml的解决方案比循环更快,就纯性能而言。@Max Favilli您必须测试它才能确定,但从概念上讲,您必须遍历字符串一次,用标记替换逗号,然后再次解析XML,然后循环遍历XML中的每个元素。当然,您可以增强我的循环,前几天我很快就这样做了,不改变列表,只跟踪子字符串的起始点和结束点,如果您计算整个字符串中下一个逗号的搜索次数,这只会导致1次通过2次。还要记住,XML在构建和维护树时有额外的开销。
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)
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
string[] tags = tagscsv.Split(',');
var output = from q in db.Table where !tags.Contains(q) select q;