SQL Server 变量名“@”已声明,变量名在查询批处理或存储过程中必须是唯一的,在c#

rks48beu  于 2022-12-03  发布在  C#
关注(0)|答案(7)|浏览(573)

变量名“@LockState”已声明。变量名在查询批处理或存储过程中必须是唯一的。
当我执行下面这段代码时,在第二个@LockState上的sql参数上出现上述错误。

private void btn_lock2_Click(object sender, EventArgs e)
{
  rwd.command = new SqlCommand();
  rwd.command.Connection = rwd.connection;

  try
  {
    if ((txt2.Text == "")| (txt_desc2.Text == ""))
      appMessages.unCompleteFields();
    else
    {
      long from = long.Parse(this.txt2.Text);
      long to = long.Parse(this.txt3.Text);
      if (from <= to)
      {
        for (long counter = from; counter <= to; counter++) 
        {
          string upd = "update card set LockState=@lockstate,
          card_descr=@card_descr where [cardNumber] = N'{0}'";
          rwd.command.CommandText = upd;
          rwd.command.Parameters.Add(new SqlParameter("@LockState",
          SqlDbType.NVarChar)).Value =1;
          rwd.command.Parameters.Add(new SqlParameter("@card_descr",
          SqlDbType.NVarChar)).Value = txt_desc2.Text;
          rwd.connection.Open();
          rwd.command.ExecuteScalar();
          rwd.connection.Close();
        }
      appMessages.successfulyUpdated();
      }
      else
      {
        appMessages.unsuccessfulyUpdated();
      }
      this.txt1.Text = "";
      this.txt2.Text = "";
    }
  }
  catch (Exception exp) { throw exp; }
  }
}
jhdbpxl9

jhdbpxl91#

您在循环的每次迭代中多次添加相同的参数。
在每次循环迭代后添加rwd.command.Parameters.Clear()

for (long counter = from; counter <= to; counter++)
{
    rwd.command.Parameters.Clear();

    string upd = "update card set LockState=@lockstate, card_descr=@card_descr where [cardNumber] = N'{0}'";
    rwd.command.CommandText = upd;
    rwd.command.Parameters.Add(new SqlParameter("@LockState",
    SqlDbType.NVarChar)).Value =1;
    rwd.command.Parameters.Add(new SqlParameter("@card_descr",
    SqlDbType.NVarChar)).Value = txt_desc2.Text;
    rwd.connection.Open();
    rwd.command.ExecuteScalar();
    rwd.connection.Close();
}

或在循环前添加参数:

rwd.command.Parameters.Add(new SqlParameter("@LockState", SqlDbType.NVarChar));
rwd.command.Parameters.Add(new SqlParameter("@card_descr", SqlDbType.NVarChar));

然后在循环中:

for (long counter = from; counter <= to; counter++)
{
    string upd = "update card set LockState=@lockstate,
    card_descr=@card_descr where [cardNumber] = N'{0}'";
    rwd.command.CommandText = upd;

    rwd.command.Parameters["@LockState"].Value =1;
    rwd.command.Parameters["@card_descr"].Value = txt_desc2.Text;

    rwd.connection.Open();
    rwd.command.ExecuteScalar();
    rwd.connection.Close();
}
vnjpjtjt

vnjpjtjt2#

因为您在每次迭代中共享该命令,所以在循环开始时清除参数。

for (long counter = from; counter <= to; counter++) 
{
  rwd.command.Parameters.Clear();

但我只会在循环之前定义它,在循环中设置值,如下所示

rwd.command.Parameters.Add("@LockState",SqlDbType.NVarChar);
rwd.command.Parameters.Add("@card_descr",SqlDbType.NVarChar);

for (long counter = from; counter <= to; counter++) 
{
    rwd.command.Parameters["@LockState"].Value = 1;
    rwd.command.Parameters["@card_descr"].Value = txt_desc2.Text;
    // ...
}

附注:
你有[cardNumber] = N'{0}'",但是从来没有为它设置值。你最好也为cardNumber使用参数。

utugiqy6

utugiqy63#

使用rwd.命令.执行标量();参数:clear();

ergxz8rk

ergxz8rk4#

我的答案基本上是对其他两个现有答案(来自@gzaxx和@Damith)的扩展,这两个答案都是正确的。
在每个循环迭代中使用相同的SqlCommand示例,因此不必(也不应该)在循环中执行任何初始化操作。
其他人已经写过的是,在循环中添加参数的定义是问题的原因,因为结果是,随着循环的迭代,您试图定义每个参数的次数。
我认为您还应该考虑将其他代码移出循环,这基本上意味着将此代码从循环中移除:

string upd = "update card set LockState=@lockstate,
card_descr=@card_descr where [cardNumber] = N'{0}'";
rwd.command.CommandText = up
rwd.command.Parameters.Add(new SqlParameter("@LockState", SqlDbType.NVarChar)).Value =1;
rwd.command.Parameters.Add(new SqlParameter("@card_descr", SqlDbType.NVarChar)).Value = txt_desc2.Text;
rwd.connection.Open();

并将其等效项放在循环之前:

string upd = "update card set LockState=@lockstate,
card_descr=@card_descr where [cardNumber] = N'{0}'";
rwd.command.CommandText = up
SqlParameter lockStateParam = rwd.command.Parameters.Add("@LockState",SqlDbType.NVarChar);
SqlParameter cardDescrParam = rwd.command.Parameters.Add("@card_descr",SqlDbType.NVarChar);
rwd.connection.Open();

您还需要替换设置参数值的方式,将以下代码放在循环中,而不是删除的代码:

lockStateParam.Value = 1;
cardDescrParam.Value = txt_desc2.Text;

当我们把打开连接的操作移出循环时,我们也需要把关闭连接的操作移出循环,所以下面的指令是:

rwd.connection.Close();

整个操作为我们提供了以下代码块:

string upd = "update card set LockState=@lockstate,
card_descr=@card_descr where [cardNumber] = N'{0}'";
rwd.command.CommandText = up
SqlParameter lockStateParam = rwd.command.Parameters.Add("@LockState",SqlDbType.NVarChar);
SqlParameter cardDescrParam = rwd.command.Parameters.Add("@card_descr",SqlDbType.NVarChar);
rwd.connection.Open();
for (long counter = from; counter <= to; counter++) 
{
  lockStateParam.Value = 1;
  cardDescrParam.Value = txt_desc2.Text;
  rwd.command.ExecuteScalar();
}
rwd.connection.Close();

当进一步查看时,我发现每次迭代实际上都使用非常相同的参数值,因此-如果这不是简化StackOverflow代码的结果-这意味着您基本上一次又一次地执行非常相同的更新。
我会假设它实际上是一个简化的代码(正如@Damith所指出的)您似乎是在按cardNumber列过滤更新的行。看起来有点奇怪的是,您似乎使用了字符串格式,用文本替换了{0}占位符。如果是这样,那么您必须在循环中设置CommandText属性。但我更愿意考虑按照@Damith的建议去做,因此添加了第三个命令参数。
顺便说一句:如果提供的答案对你有效(基本上所有的答案都应该有效),考虑接受其中的一个(可能是这里出现的第一个)。

xzabzqsa

xzabzqsa5#

由于您在循环的最顶部使用循环命令(foreach、for等),因此请添加一个

rwd.Parameters.Clear();

每次迭代的时候都会清除参数,然后解决这个问题,我遇到了同样的错误,这个解决了。

bhmjp9jg

bhmjp9jg6#

我把rwd.Parameters.Clear();放到循环中,它解决了这个问题。

fnx2tebb

fnx2tebb7#

如果您正在添加参数并进行查询,则在每次执行后,确保清除之前的参数值command.Parameters.Clear();
例如:

using (SqlCommand command = new SqlCommand()){
      foreach (var data in result.Values)
           {
             command.Connection = conn;
             command.CommandType = CommandType.Text;
             command.CommandText = "INSERT INTO studentTable (student) VALUES (@student)";

             command.Parameters.AddWithValue("@student", data.student);

             command.ExecuteNonQuery();

         // clear the previous paramter data else it will throw 
         // variable already declared exception
             command.Parameters.Clear(); 
          }
}

希望能帮上忙。

相关问题