我必须使用用户在网页上选择的值
来创建一个字符串假设我需要为具有不同搜索条件的多台计算机显示文件...
我目前使用此代码:
DataTable dt = new DataTable();
SqlConnection connection = new SqlConnection();
connection.ConnectionString = ConfigurationManager
.ConnectionStrings["DBConnectionString"].ConnectionString;
connection.Open();
SqlCommand sqlCmd = new SqlCommand
("SELECT FileID FROM Files
WHERE MachineID=@machineID and date= @date", connection);
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlCmd);
sqlCmd.Parameters.AddWithValue("@machineID", machineID);
sqlCmd.Parameters.AddWithValue("@date", date);
sqlDa.Fill(dt);
现在这是一个固定查询,用户只有一台机器,只选择一个日期......
我想根据他/她选择的内容,在用户有多个搜索选项(如类型或大小)的情况下进行查询。
此外,如果他/她可以选择多台机器......
SELECT FileID FROM Files
WHERE (MachineID=@machineID1 or MachineID = @machineID2...)
AND (date= @date and size=@size and type=@type... )
所有这些都发生在运行时...否则我必须创建一个for
循环来逐个放置多台机器......并根据用户选择的情况进行多次查询...
这非常有趣,我可以使用一些帮助......
答案 0 :(得分:2)
您可以使用WHERE MachineID IN ('Machine1', 'Machine2', 'Machine3', ... 'MachineN')
然后在你的循环中你只需添加1..n机器。 IN子句使用1个元素或n个元素,因此它应该没问题。
但是,我会考虑使用存储过程来执行此操作,而不是将SQL硬编码到应用程序中。
答案 1 :(得分:2)
构建一个真实的表并将机器ID加载到其中。
然后你的SQL将是:
where MachineID in ( select MachineID from userMachine where userID = x)
完成后,删除userID的所有行:
delete from userMachine where userID = x.
答案 2 :(得分:2)
如果要通过动态SQL执行此操作,则需要构建对IN函数的调用。 (例如In(id1,id2,id3 ......)
private string GetSql( IList<int> machineIds )
{
var sql = new StringBuilder( "SELECT FileID FROM Files Where MachineID In(" );
for( var i = 0; i < machineIds.Count; i++ )
{
if ( i > 0 )
sql.Append(", ")
sql.Append("@MachineId{0}", i);
}
sql.Append(" ) ");
//additional parameters to query
sql.AppendLine(" And Col1 = @Col1" );
sql.AppendLine(" And Col2 = @Col2 ");
...
return sql.ToString();
}
private DataTable GetData( IList<int> machineIds, string col1, int col2... )
{
var dt = new DataTable();
var sql = GetSql( machineIds );
using ( var conn = new SqlConnection() )
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["DBConnectionString"].ConnectionString;
using ( var cmd = new SqlCommand( sql, conn ) )
{
conn.Open();
for( var i = 0; i < machineIds.Count; i++ )
{
var parameterName = string.Format("@MachineId{0}", i );
cmd.Parameters.AddWithValue( parameterName, machineIds[i] );
}
cmd.Parameters.AddWithValue( "@Col1", col1 );
cmd.Parameters.AddWithValue( "@Col2", col2 );
...
using ( var da = new SqlDataAdapter( cmd ) )
{
da.Fill( dt );
}
}
}
return dt;
}
答案 3 :(得分:1)
理想情况下,您正试图获得类似于动态创建“(1,2,3,4)中的MachineID”的解决方案。
选项1
有很多方法可以完成此任务,将逗号分隔的字符串传递给存储过程并动态构建sql字符串,然后调用“EXEC sp_executesql @sql” WHERE IN (array of IDs)
选项2
您可以传入一串逗号分隔值,然后将值解析为自己的临时表,然后加入它 http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm
选项3 - 我的选择
现在,您可以使用XML传递值数组,然后轻松选择数组项。 http://support.microsoft.com/kb/555266
答案 4 :(得分:1)
我还建议使用存储过程,否则你会对SQL注入攻击开放 - 尤其是在你根据用户输入构建字符串的情况下。
类似的东西:
a' or 1=1; -- Do bad things
您可以在SQL中使用sp_executesql来运行一个SQL语句,该语句是使用像@dcp建议的where
子句构建的,虽然它不能很好地优化,但它可能是一个快速命令来运行。
SQL Injection attacks by example
实现这一目标的一种方法是使用charindex。此示例演示了如何在传递空格分隔的id列表时运行存储过程:
declare @machine table (machineId int, machineName varchar(20))
declare @files table (fileId int, machineId int)
insert into @machine (machineId, machineName) values (1, 'machine')
insert into @machine (machineId, machineName) values (2, 'machine 2.0')
insert into @machine (machineId, machineName) values (3, 'third machine')
insert into @machine (machineId, machineName) values (4, 'machine goes forth')
insert into @machine (machineId, machineName) values (5, 'machine V')
insert into @files (fileId, machineId) values (1, 3)
insert into @files (fileId, machineId) values (2, 3)
insert into @files (fileId, machineId) values (3, 2)
insert into @files (fileId, machineId) values (4, 1)
insert into @files (fileId, machineId) values (5, 3)
insert into @files (fileId, machineId) values (6, 5)
declare @machineText1 varchar(100)
declare @machineText2 varchar(100)
declare @machineText3 varchar(100)
set @machineText1 = '1 3 4'
set @machineText2 = '1'
set @machineText3 = '5 6'
select * from @files where charindex(rtrim(machineId), @machineText1, 1) > 0
-- returns files 1, 2, 4 and 5
select * from @files where charindex(rtrim(machineId), @machineText2, 1) > 0
-- returns file 4
select * from @files where charindex(rtrim(machineId), @machineText3, 1) > 0
--returns file 6
因此,您可以创建此存储过程以实现您的目标:
create procedure FilesForMachines (@machineIds varchar(1000))
as
select * from [Files] where charindex(rtrim(machineId), @machineIds, 1) > 0
charindex提示来自BugSplat。
答案 5 :(得分:1)
通常,当我想创建“搜索”类型查询时,我使用可选参数。这允许我向参数发送一些内容或不发送内容,使查询从模糊变为非常具体。
示例:
SELECT
COL1,
COL2,
COL3
FROM TABLE
WHERE (@COL1 IS NULL OR @COL1 = '' OR @COL1 = COL1)
如上所述,如果传入NULL或BLANK,则不会将参数添加到查询中。如果您输入了一个值,那么它将用于比较。