Sql 如何使用来自HTTP表单的值列表执行类似于“notin”的WHERE?
我用C语言开发了一个web应用程序,其中一个页面显示SQL查询的输出;该查询是对存储过程的linq调用,我使用的是SQL Server 2008 其中一列显示与结果行关联的标记;在同一页面上,将显示一个复选框列表,每个复选框对应一个标记,如果用户打开或关闭一个或多个复选框,我将过滤查询 我最简单的SQL解决方案对我们来说不是如下所示: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
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;