为什么我得到错误 必须声明标量变量"@x" .当查询在 SQL 窗口中工作时?



我得到的错误是"必须声明标量变量"@x";

我试图声明一个变量@x并使他成为NVARCHAR(50)

然后我想从中减去一个叫做@z

的金额,最后用@x -@z

的结果更新服务器中名为Stock的表。
cmd.CommandText = "DECLARE @x AS NVARCHAR(50)";
cmd.ExecuteScalar();
for(int i=0;i<length;i++)
{
for(int j=0;j<2;j++)
{
//for ease of use
string name = dt.Rows[i][0].ToString();
string amount = dt.Rows[i][1].ToString();

cmd.CommandText = "SELECT @x = amount FROM Stock WHERE name = '"+name +"'";
cmd.ExecuteScalar();// im getting the error here but assume it will be in every executescalar
Thread.Sleep(100);
Console.WriteLine("end update");
cmd.CommandText = "DECLARE @z AS integer";
cmd.ExecuteScalar();
Thread.Sleep(100);
Console.WriteLine("end update");
cmd.CommandText = "SELECT @z = " + amount;
cmd.ExecuteScalar();
Thread.Sleep(100);
Console.WriteLine("end update");
cmd.CommandText = "UPDATE stock SET amount = @x -@z WHERE name='" + name + "'";
cmd.ExecuteScalar();
Thread.Sleep(100);
Console.WriteLine("end update");
}
}

dt rows很好,并给出适当的值

你的代码有很多问题:

  • 首先,你不能在一个SQL批处理中声明一个变量,然后使用它,它必须是同一个批处理。
  • 不要将数据连接到你的查询中,这是危险的,可能会导致注入攻击和语法错误。使用参数代替。
  • SELECT @x = amount没有意义:如果你想使用参数检索数据,那么你需要声明它,如果你想使用ExecuteScalar检索,那么你只需要SELECT amount
  • 无论哪种方式,您都不需要SELECT somethingUPDATE something,只需在一个UPDATE语句中进行计算。
  • 不清楚第二个for循环应该做什么,它只是做同样的事情三次。
  • 您希望通过Thread.Sleep实现什么?

所以你的代码变成:

const string query = @"
UPDATE stock
SET amount = amount - @amount
WHERE name = @name;
";
using (var conn = new SqlConnection(YourConnectionString))
using (var cmd = new SqlCommand(query, conn))
{
// add parameters with no values
cmd.Parameters.Add("@name", SqlDbType.VarChar, 100);  // select correct types and lengths
cmd.Parameters.Add("@amount", SqlDbType.Decimal);
conn.Open();
foreach (DataRow row in dt.Rows)
{
// overwrite the values here
cmd.Parameters["@name"].Value = row[0];
cmd.Parameters["@amount"].Value = row[1];
cmd.ExecuteNonQuery();
}
}

但是,对于大量的行,这仍然很慢。使用表值参数来批量完成整个更新会更有效。

首先,创建一个表类型。我通常有一些标准的格式,例如字符串和小数的两列格式:
CREATE TYPE dbo.StringDecimal AS TABLE (
String varchar(100) PRIMARY KEY,
Number decimal(18,9)
);

那么你可以这样使用:

const string query = @"
UPDATE s
SET amount = s.amount - t.Number
FROM stock s
JOIN @tmp t ON t.String = s.name;
";
using (var conn = new SqlConnection(YourConnectionString))
using (var cmd = new SqlCommand(query, conn))
{
cmd.Parameters.Add(new SqlParameter("@tmp", SqlDbType.Structured) {
Value = dt,
TypeName = "dbo.StringDecimal",
});
conn.Open();
cmd.ExecuteNonQuery();
}

dt必须有正确顺序的两列。

最新更新