我很久以前就听说过参数化的sql查询,但我从来没有真正关注它,因为我习惯于编写完整的sql语句。我知道它提高了sql注入的安全性,所以现在可能是适应变化的好时机,即使为时已晚。我从这个网站http://www.codinghorror.com/blog/2005/04/give-me-parameterized-sql-or-give-me-death.html得到了这个。因此所有学分都归作者所有。我注意到参数化sql查询的所有示例都有paremeter计数限制。一个例子如下所示。
SqlConnection conn = new SqlConnection(_connectionString);
conn.Open();
string s = "SELECT email, passwd, login_id, full_name FROM members WHERE email = @email";
SqlCommand cmd = new SqlCommand(s);
cmd.Parameters.Add("@email", email);
SqlDataReader reader = cmd.ExecuteReader();
这相当于
SELECT email, passwd, login_id, full_name FROM members WHERE email = 'x';
我通过阅读在线教程自学了所有编程,我真的没有人帮助我。我陷入完整的sql语句查询的原因是我无法弄清楚如何使用无限参数进行参数化sql查询。有没有办法做到这一点?该示例仅接受1个参数,即“email”字段。它从给定的sql语句中选择4个字段。我的问题是......有没有什么方法可以用5,6,7或100个选定字段进行参数化sql查询,以及WHERE子句下的条件?如果可以,则在使用INSERT语句时特别有用。非常感谢你。
这个例子在C#中,但是非常感谢任何VB.NET或相同的C#实现。感谢。
答案 0 :(得分:4)
一种可能的解决方案是使用Dictionary object传递参数名称和值。 Dictionary对象包含键和值的集合,这正是单个SqlParameter的形式 - 表单中的单个键/值容器:< / p>
Key = @Value
集合可以包含任意数量的项目,例如:
new Dictionary<String, Object>
{
{ "@Name", "Anonymous" },
{ "@Age", 25 },
{ "@Street", "Highway" },
{ "@Number", "1001" },
{ "@City", "NoName" }
}
在上面的示例中,键的类型为String,而值的类型为Object。 Object允许任意类型的参数值(稍后在代码示例中进行说明)。
创建动态SQL语句的一种可能性是:
代码可能如下所示:
// extract all repetitive tasks
// Create an array of SqlParameters from the given Dictionary object.
// The parameter value is of type Object in order to allow parameter values of arbitrary types!
// The .NET Framework converts the value automatically to the correct DB type.
// MSDN info: http://msdn.microsoft.com/en-us/library/0881fz2y%28v=vs.110%29.aspx
private SqlParameter[] dictionaryToSqlParameterArray(Dictionary<string, object> parameters)
{
var sqlParameterCollection = new List<SqlParameter>();
foreach (var parameter in parameters)
{
sqlParameterCollection.Add(new SqlParameter(parameter.Key, parameter.Value));
}
return sqlParameterCollection.ToArray();
}
// sqlQuery is the complete parametrised query
// for example like: INSERT INTO People(Name, Age, Street) VALUES(@Name, @Age, @Street)
private SqlCommand createSqlCommand(String sqlQuery, Dictionary<String, object> parameters)
{
SqlCommand command = new SqlCommand(sqlQuery);
command.Parameters.AddRange(dictionaryToSqlParameterArray(parameters));
return command;
}
现在,带有动态参数计数的调用将如下所示:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
string sqlQuery = "SELECT email, passwd, login_id, full_name FROM members WHERE email = @email AND name = @name";
// using the newly created method instead of adding/writing every single parameter manually
SqlCommand command = createSqlCommand(sqlQuery, new Dictionary<String, Object>
{
{ "@email", "test@test.com" },
{ "@name", "test" }
});
SqlDataReader reader = command.ExecuteReader();
这是一个好的开始,但这仍然不是很动态,因为我们每次都需要编写完整的查询(我们只保存 command.Parameters.Add 的输入)。让我们改变这个以便输入更少:
// create a parametrised SQL insert command with arbitrary count of parameters for the given table
private SqlCommand createSqlInsert(String tableName, Dictionary<String, object> parameters)
{
// the sql insert command pattern
var insertQuery = @"INSERT INTO {0}({1}) VALUES({2})";
// comma separated column names like: Column1, Column2, Column3, etc.
var columnNames = parameters.Select (p => p.Key.Substring(1)).Aggregate ((h, t) => String.Format("{0}, {1}", h, t));
// comma separated parameter names like: @Parameter1, @Parameter2, etc.
var parameterNames = parameters.Select (p => p.Key).Aggregate ((h, t) => String.Format("{0}, {1}", h, t));
// build the complete query
var sqlQuery = String.Format(insertQuery, tableName, columnNames, parameterNames);
// debug
Console.WriteLine(sqlQuery);
// return the new dynamic query
return createSqlCommand(sqlQuery, parameters);
}
// create a parametrised SQL select/where command with arbitrary count of parameters for the given table
private SqlCommand createSqlWhere(String tableName, Dictionary<String, object> parameters)
{
// the sql select command pattern
var whereQuery = @"SELECT * FROM {0} WHERE {1}";
// sql where condition like: Column1 = @Parameter1 AND Column2 = @Parameter2 etc.
var whereCondition = parameters.Select (p => String.Format("{0} = {1}", p.Key.Substring(1), p.Key)).Aggregate ((h, t) => String.Format("{0} AND {1}", h, t));
// build the complete condition
var sqlQuery = String.Format(whereQuery, tableName, whereCondition);
// debug
Console.WriteLine(sqlQuery);
// return the new dynamic query
return createSqlCommand(sqlQuery, parameters);
}
现在, SELECT 命令的创建将如下所示:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
// specify only table name and arbitrary count of parameters
var getPersonSqlCommand = createSqlWhere("People", new Dictionary<String, Object>
{
{ "@Name", "J.D." },
{ "@Age", 30 }
});
SqlDataReader reader = getPersonSqlCommand.ExecuteReader();
createSqlWhere 方法将返回带有查询的初始化SqlCommand:
SELECT * FROM People WHERE Name = @Name AND Age = @Age
INSERT 也会很短:
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
// specify only table name and arbitrary count of parameters
var addPersonSqlCommand = createSqlInsert("People", new Dictionary<String, Object>
{
{ "@Name", "Anonymous" },
{ "@Age", 25 },
{ "@Street", "Test" }
});
addPersonSqlCommand.ExecuteNonQuery();
相应的SQL命令如下所示:
INSERT INTO People(Name, Age, Street) VALUES(@Name, @Age, @Street)
可以以相同的方式创建其他SQL命令,如DELETE,UPDATE等。新参数只应添加到一个地方 - 在字典中。
不可否认,最初的努力不仅仅是编写一种方法,但如果新方法被多次使用(几次),它将获得回报 - 例如五种参数化选择和/或者在具有不同参数的五个不同表上插入,在小型和平均大小的软件项目中总是如此。
答案 1 :(得分:1)
只需创建一个方法:
public void unlimQuery(string query,params object[] args)
{
SqlConnection conn = new SqlConnection(_connectionString);
conn.Open();
string s =query;
SqlCommand cmd = new SqlCommand(s);
For(int i=0;i< args.Length;i++)
cmd.Parameters.Add("@param"+i, args[i]);
SqlDataReader reader = cmd.ExecuteReader();
}
示例:
unlimQuery("INSERT INTO CUSTOMERS(ID,NAME,AGE,ADRESS,COUNTRY) VALUES(@param0,@param1,@param2,@param3,@param4)",5,"Ali",27,"my City","England");
说明:
c#中的params关键字使您可以插入指定类型的无限参数,因此添加的参数(5,“Ali”,27,“my city”,“England”)将被转换为数组然后将对象传递给Method
在方法内你将得到一个对象数组,所以对于你创建参数的每个对象,他的别名是@paramX
,其中X是参数的索引(在params数组中),然后sqlCommad将用cmd.Parameters.Add("@param"+i, args[i])
子句
所以@ param0 =&gt; 5,.....
答案 2 :(得分:0)
我想你只需要改变这个
cmd.Parameters.Add("@email", email);
到
cmd.Parameters.AddWithValue("@email", email);