我正在尝试查询现有的访问数据库,并允许用户为WHERE子句选择多个值。我一直在使用此网站上的代码由用户Mark Brackett提供:
string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";
string[] paramNames = tags.Select(
(s, i) => "@tag" + i.ToString()
).ToArray();
string inClause = string.Join(",", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
for(int i = 0; i < paramNames.Length; i++) {
cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
}
}
给出了这个:
cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0,@tag1,@tag2,@tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"
这非常有效,但我也想要以下功能。如果用户决定不输入任何值(在此示例中,如果tags数组为空),则我希望返回所有结果。实际上只是一个SELECT * FROM Tags。
答案 0 :(得分:3)
像
这样的东西string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags {0}";
string[] paramNames = tags.Select(
(s, i) => "@tag" + i.ToString()
).ToArray();
string cmdWhere = paramNames.Length > 0 ? String.Format("WHERE Name IN ({0})", string.Join(",", paramNames)) : "";
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, cmdWhere)))
{
for (int i = 0; i < paramNames.Length; i++)
{
cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
}
}
因此,如果您没有参数,则最后不添加where子句。
答案 1 :(得分:2)
尝试
string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags" ;
string cond=" WHERE Name IN ({0})";
string[] paramNames = tags.Select(
(s, i) => "@tag" + i.ToString()
).ToArray();
if(paramNames.Length>0){
string inClause = string.Join(",", paramNames);
cmdText=string.Concat(cmdText,string.Format(cond, inClause));
}
using (SqlCommand cmd = new SqlCommand(cmdText) {
for(int i = 0; i < paramNames.Length; i++) {
cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
}
}
答案 2 :(得分:1)
为什么不将它们连接起来而不是为每个项目设置一个参数?
我不确定这是否适用于MS Access,但这是我用于MS SQL的内容:
DECLARE @tagIds nvarchar(max)
SELECT * FROM Tags where @tagIds is null or tagId IN (select number from dbo.iter_intlist_to_tbl(@tagIds))
所以@tagIds
是一个以逗号分隔的ID列表,我只是用函数解析它。如果@tagIds
为null,则返回所有标记。
iter_intlist_to_tbl()
函数如下所示:
CREATE FUNCTION [dbo].[iter_intlist_to_tbl] (@list nvarchar(MAX))
RETURNS @tbl TABLE (listpos int IDENTITY(1, 1) NOT NULL,
number int NOT NULL) AS
BEGIN
DECLARE @startpos int,
@endpos int,
@textpos int,
@chunklen smallint,
@str nvarchar(4000),
@tmpstr nvarchar(4000),
@leftover nvarchar(4000)
SET @textpos = 1
SET @leftover = ''
WHILE @textpos <= datalength(@list) / 2
BEGIN
SET @chunklen = 4000 - datalength(@leftover) / 2
SET @tmpstr = ltrim(@leftover +
substring(@list, @textpos, @chunklen))
SET @textpos = @textpos + @chunklen
SET @startpos = 0
SET @endpos = charindex(',' COLLATE database_default, @tmpstr)
WHILE @endpos > 0
BEGIN
SET @str = substring(@tmpstr, @startpos + 1,
@endpos - @startpos - 1)
IF @str <> ''
INSERT @tbl (number) VALUES(convert(int, @str))
SET @startpos = @endpos
SET @endpos = charindex(',' COLLATE database_default,
@tmpstr, @startpos + 1)
END
SET @leftover = right(@tmpstr, datalength(@tmpstr) / 2 - @startpos)
END
IF ltrim(rtrim(@leftover)) <> ''
INSERT @tbl (number) VALUES(convert(int, @leftover))
RETURN
END
GO
有关解析逗号分隔列表的更多信息,请参阅http://www.sommarskog.se/arrays-in-sql-2005.html。虽然我想你会在MS Access中以不同的方式做到这一点
答案 3 :(得分:1)
我假设如果任何标签为空
if (@tag0 is null or @tag1 is null or @tag2 is null or @tag3 is null)
begin
select * from tags
end
else
begin
SELECT * FROM Tags WHERE Name IN (@tag0,@tag1,@tag2,@tag3)
end
答案 4 :(得分:0)
将where子句放在变量中并使CommandText像cmd.CommandText = SELECT + WHERE
一样
何时:SELECT = "SELECT * FROM Tags"
WHERE = "WHERE " + "Name IN (@tag0 ....)"
如果没有参数变量WHERE将是=“”
答案 5 :(得分:0)
我修改了现有的。这将有效。
string cmdText = "SELECT * FROM Tags ";
string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string where = null;
if (tags != null)
{
where = "WHERE Name IN (";
foreach (string tag in tags)
{
where += "'" + tag + "',";
}
where = where.TrimEnd(',') + ")";
}
if (!string.IsNullOrEmpty(where))
{
cmdText += where;
}