使用C#编写的MySQL参数化查询

35

我有以下代码(我已经包含了我认为所有相关的部分):

private String readCommand = "SELECT LEVEL FROM USERS WHERE VAL_1 = ? AND VAL_@ = ?;";
public bool read(string id)
{
    level = -1;
    MySqlCommand m = new MySqlCommand(readCommand);
    m.Parameters.Add(new MySqlParameter("", val1));
    m.Parameters.Add(new MySqlParameter("", val2));
    MySqlDataReader r = m.ExecuteReader();
    if (r.HasRows)
        level = Convert.ToInt32(r.GetValue(0).ToString());
    r.Close();
    return true;
}

当我运行这段代码时,我在添加第一个参数时遇到了IndexOutOfBoundsException异常。我做错了什么?

6个回答

58

可以尝试这个:

private String readCommand = 
             "SELECT LEVEL FROM USERS WHERE VAL_1 = @param_val_1 AND VAL_2 = @param_val_2;";

public bool read(string id)
{
    level = -1;
    MySqlCommand m = new MySqlCommand(readCommand);
    m.Parameters.AddWithValue("@param_val_1", val1);
    m.Parameters.AddWithValue("@param_val_2", val2);
    level = Convert.ToInt32(m.ExecuteScalar());
    return true;
}

8
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
    MySqlConnection con = new MySqlConnection("server=localhost;User Id=root;database=result;password=1234");
    con.Open();

    MySqlCommand cmd = new MySqlCommand("Select * from users where username=?username and password=?password", con);
    cmd.Parameters.Add(new MySqlParameter("username", this.Login1.UserName));
    cmd.Parameters.Add(new MySqlParameter("password", this.Login1.Password)); 

    MySqlDataReader dr = cmd.ExecuteReader();
    if (dr.HasRows ==true)
    {
        e.Authenticated = true;
    }
}

4

您需要在查询中使用命名参数。例如:

String readCommand = "SELECT LEVEL FROM USERS WHERE VAL_1 = ?param1 AND VAL_2 = ?param2";

然后,在实例化MySqlParameter对象时,要传递参数名称,如下所示:
m.Parameters.Add(new MySqlParameter("param1", val1));

1
MySQL的参数是否以'?'开头,而不像SQL Server中的'@'?我以为它们是一样的。有趣! - Chris
1
用户在http://dev.mysql.com/doc/refman/5.0/en/connector-net-examples-mysqlcommand.html中的评论如此说。 - Chry Cheng
当您提到语法细节时,我要指出参数值将会“自引用”。因此,在字符串数据的值周围不需要加上引号。这个例子是正确的,但缺少引号非常微妙,所以我想指出来。 - James

3
m.Parameters.AddWithValue("parameter",value) 

使用参数化查询将是更好的选择。

2

如果您需要多次执行SQL语句,则应使用以下方式:

conn.Open();
cmd.Connection = conn;

cmd.CommandText = "INSERT INTO myTable VALUES(NULL, @number, @text)";
cmd.Prepare();

cmd.Parameters.AddWithValue("@number", 1);
cmd.Parameters.AddWithValue("@text", "One");

for (int i=1; i <= 1000; i++)
{
    cmd.Parameters["@number"].Value = i;
    cmd.Parameters["@text"].Value = "A string value";

    cmd.ExecuteNonQuery();
}

第一次不使用“ExecuteNonQuery”,只使用虚假值添加参数,然后在循环内添加实际值。

请参考此链接:https://dev.mysql.com/doc/connector-net/en/connector-net-programming-prepared-preparing.html


2

我认为MySql.Data类不支持无名参数。如果你想使用它们,可以通过ODBC驱动程序访问你的MySql数据库,它们支持这种方式。

你需要在查询中为参数命名:

"SELECT LEVEL FROM USERS WHERE VAL_1 = @val1 AND VAL_2 = @val2;"

我选择了参数指示符“@”,但是最近版本的MySql.Data支持“@”和“?”两种形式。
然后更新您的参数构造函数以传递正确的参数名称(您不需要在此处包括参数指示符,尽管如果您这样做也没有任何影响)。
m.Parameters.Add(new MySqlParameter("val1", val1));

提示:您可能已经知道了,或者这段代码片段中被省略了,但我认为您忘记对ExecuteReader的实例调用Read方法。


我在代码中确实忘记了,直到执行路径到达那里才发现。我正在重新设计一堆旧查询,并且一些代码正在被移动,这本身就很容易出错。感谢您的帮助! - Elie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接