【问题标题】:error with addwithvalue sql parameteraddwithvalue sql参数出错
【发布时间】:2016-07-19 16:23:09
【问题描述】:

有人建议我用 SqlParameter 替换我的代码,以避免将 SQL 注入作为安全问题,但我的理解有限。我尝试实现它,但我遇到了一个错误:

必须声明标量变量

我尝试了其他线程的其他建议,即为每次插入实现一个新参数,而不是为每个条目替换参数值。

String query = "INSERT INTO EmpInfo(EmpYear, EmpStatus, LName, FName, JobTitle, EmpPay, EmpDoB, EmpSex, EmpAddr, EmpCity, EmpState, EmpZIP, EmpCountry, EmpEAddr, EmpTelNo, EmpMobileNo, EmpDate) " +
               "VALUES('"+EmpYear+"', @EmpStatus, @LName, @FName, @JobTitle, @EmpPay, @EmpDoB, @EmpSex, @EmpAddr, @EmpCity, @EmpState, @EmpZIP, @EmpCountry, @EmpEAddr, @EmpTelNo, @EmpMobileNo, getdate())";
String query2 = "INSERT INTO AccountInfo(LName, FName, EmpTemplate, AccountType, EmpStatus, EmpDate) " +
                "VALUES (@LName, @FName, @EmpTemplate, @AccountType, @EmpStatus, GetDate())";

using (SqlConnection connection = new SqlConnection("Data Source=RB-DESKTOP;Initial Catalog=TimeDB;Persist Security Info=True;User ID=sa;Password=bautista7"))
{
    SqlCommand cmd = new SqlCommand(query, connection);
    cmd.Connection = conn;

    conn.Open();
    cmd.CommandText = "SELECT MAX(EmpID) FROM EmpInfo";

    SqlDataReader rdr = cmd.ExecuteReader();
    rdr.Close();

    SqlCommand command = new SqlCommand(query, cmd.Connection);
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpYear", Value = EmpYear });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpStatus", Value = "Active" });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@LName", Value = regLname_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@FName", Value = regFname_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@JobTitle", Value = "NULL" });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpPay", Value = PayType_cb.SelectedItem.ToString() });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpDoB", Value = regDob_dtp.Value.Date });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpSex", Value = gender });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpAddr", Value = regAddr_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpCity", Value = regCity_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpState", Value = regState_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpZIP", Value = regZip_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpCountry", Value = regCountry_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpEAddr", Value = regEmail_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpTelNo", Value = regTel_text.Text });
    command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpMobileNo", Value = regMob_text.Text });

    command.ExecuteNonQuery();
    command.Parameters.Clear();

    SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
    command.Parameters.AddWithValue("@LName", regLname_text.Text);
    command.Parameters.AddWithValue("@FName", regFname_text.Text);
    command.Parameters.AddWithValue("@EmpTemplate", template);
    command.Parameters.AddWithValue("@AccountType", AcctType_cb.SelectedItem.ToString());
    command.Parameters.AddWithValue("@EmpStatus", "Active");

    command.ExecuteNonQuery();

    command.Parameters.Clear();

【问题讨论】:

  • 错误是什么?请阅读How-to-Ask 这里是START 了解如何提高问题质量并获得更好答案的好地方。
  • 我真的很抱歉,但它写在段落上。我处理了“必须声明标量变量”的例外情况,不仅仅是一列,如果不是全部,大多数。
  • 但是哪一行导致你出现这个错误,确切的错误是什么?也可以先尝试用一个字段较少的简单表进行测试,这样你就可以更容易地关注错误。How to create a Minimal, Complete, and Verifiable example
  • 到目前为止我注意到的有 empyear、jobTitle 和 EmpPay,可能更多,因为一旦它抛出异常,它就会停止。这就是我得到的。异常来自 command.ExecuteNonQuery();出现错误“必须声明标量变量”。
  • 您还添加了@EmpYear 参数,但实际上并没有使用它。

标签: c# sql sql-server winforms


【解决方案1】:

在创建command2 之后,您使用了两次command 变量而不是command2。您收到错误是因为您清除了所有参数的command,然后添加参数(与现有查询不匹配),然后执行ExecuteNonQuery,然后引发错误。

像这样更改第二个执行语句/命令,注意在创建 command2 之后,它现在也被使用而不是重用 command

SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
command2.Parameters.AddWithValue("@LName", regLname_text.Text);
command2.Parameters.AddWithValue("@FName", regFname_text.Text);
command2.Parameters.AddWithValue("@EmpTemplate", template);
command2.Parameters.AddWithValue("@AccountType", AcctType_cb.SelectedItem.ToString());
command2.Parameters.AddWithValue("@EmpStatus", "Active");
var numberOfRecordsInserted = command2.ExecuteNonQuery();

// value of numberOfRecordsInserted should be 1

此外,当您使用完 SqlCommand 后,您可以将其处理掉,除非您计划重用完全相同的 SqlCommand 实例,否则无需调用 SqlCommand.Parameters.Clear()(至少不在贴出代码)。

【讨论】:

  • 非常感谢!你的解释真的很容易理解!我忽略了很多错误。我已经连续编码了 3 天,几乎没有睡觉,谢谢!我现在可以高枕无忧了
  • @user3442765 - 没问题。如果这是您的答案,请不要忘记使用旁边的复选框将其标记。
  • 很抱歉再次打扰您,我设法清除了错误并且 ExecuteNonQuery 正在返回受影响的行,但是当我从 SSMS 中的 empinfo 中选择 * 时,表格是空白的。
  • 我做了但是它说我的声誉低于15,虽然它被记录了,但它不能公开显示。
  • @user3442765 - 如果您的连接字符串指向与您在 SSMS 中查看的不同的数据库,则可能会发生这种情况。例如,如果您使用 LocalDb,这将是一个常见错误。或者,如果您使用的是 localdb,您可能会在每次构建时重置(覆盖文件)数据库。
【解决方案2】:

我认为你应该先尝试简化你的逻辑。我发现了一些奇怪的东西。

查询有"VALUES('"+EmpYear+"', 我想你想要@EmpYear 因为你也有

command.Parameters.Add(new SqlParameter() { ParameterName = "@EmpYear", Value = EmpYear });

另外

SqlCommand cmd = new SqlCommand(query, connection);
                              //^^^ here you use insert query
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "SELECT MAX(EmpID) FROM EmpInfo"; // But here you change it for a SELECT?

// Then you execeute a DataReader but you close it before save the result.
SqlDataReader rdr = cmd.ExecuteReader();
rdr.Close();

//Then create the insert command again
SqlCommand commad = new SqlCommand(query, cmd.Connection);

....

// clear command, I guess you want reuse it
command.Parameters.Clear();                

// now create command 2 is OK
SqlCommand command2 = new SqlCommand(query2, cmd.Connection);
                                  // ^^^ second insert query

// but add parameteres to command NOT OK
command.Parameters.AddWithValue("@LName", regLname_text.Text);

【讨论】:

  • 抱歉,我脑子里一直在拼命想解决每个问题,有时我忘记撤消更改。我改为使用 +EmpYear_=+ 来避免声明标量变量,而是在不同的列中遇到相同的错误。我会尝试你的建议,非常感谢你
  • 很抱歉再次打扰您,我设法清除了错误并且 ExecuteNonQuery 正在返回受影响的行,但是当我从 SSMS 中的 empinfo 中选择 * 时,表格是空白的。
猜你喜欢
  • 1970-01-01
  • 2014-02-02
  • 2012-11-07
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2023-04-05
相关资源
最近更新 更多