【问题标题】:Insert negative value into SQL Server decimal column throws error将负值插入 SQL Server 十进制列会引发错误
【发布时间】:2012-07-26 16:18:34
【问题描述】:

我遇到了负小数问题。

在 SQL Server 数据库中,我将 price 定义为 decimal(8,2) NULL

以及我在 C# 中使用的代码:

string query = string.Format("INSERT INTO ticket_elements " +
                             "(ticket_id, product_name, price, tax, amount) " +
                             VALUES ({0}, '{1}', '{2}', '{3}', '{4}'); SELECT SCOPE_IDENTITY();",
                                 ticket_id, pro2.ProductName, tPrice, tax, fixedAmountStr);

{2} 的价格也不是负值时,它工作正常,但是当我像-0.25 这样设置价格时,它给出了这个错误:

在数字数据类型中转换 varchar 时的算术溢出。

如何在 db 中使用负值?

更新:

但下面的代码可以正常使用负值或正值。

我真的很困惑。

string query = string.Format("INSERT INTO tickets " +
                             "(registration_date, cancellation, cancellation_date,    total_products, total_gross_price, total_net_price, pay_type, user_id, client_id)" +
                             " VALUES ('{0}', '{1}', '{2}', '{3}', '{4}',  '{5}', '{6}', {7}, {8});" +
                             " SELECT SCOPE_IDENTITY();", regData, "False", "", this.TotalProducts, totalGrossPrice, totalNetPrice, this.PayType, this.CashierId,  this.ClientId);

【问题讨论】:

  • 您将所有内容作为每个参数的字符串传递。馊主意。最好使用参数化查询(正如 Testujin 指出的那样)或确保将任何非字符串值作为文字传入(SQL 将根据列推断类型)。换句话说,去掉价格、税金和金额列参数周围的撇号(所以{2}, {3}, {4} 而不是'{2}','{3}','{4}'
  • 仍然只适用于正数。顺便提一句。 2. 代码部分是如何工作的,而 1. 不是.. 我真的厌倦了它
  • 那么我假设您的列(价格、税金、金额)之一没有指定小数。检查以确保它们都没有被创建为 DECIMAL(#,0) 或 NUMERIC(#,0)。无论哪种方式,这些列都应该是 MONEY 数据类型。
  • 谢谢!现在它的工作。问题是税是十进制的(3,2)我只是把它设为十进制(8,2)。我会将所有插入更改为参数化代码。

标签: c# sql sql-server


【解决方案1】:

不要使用 string.format 来创建查询。请改用参数化查询。

对于 SQL Server:

var aDbCommand = connection.CreateCommand();
aDbCommand.CommandText = "insert into myTable(column1,columns2) values (@param1, @param2)";
aDbCommand.Parameters.Add(new SqlParameter{Name="@param1", SqlDbType=SqlDbType.Decimal, Value = aValue});
aDbCommand.Parameters.Add(new SqlParameter{Name="@param2", SqlDbType=SqlDbType.Decimal, Value = aValue});
aDbCommand.Execute();

【讨论】:

  • 你能举个例子吗?
  • INSERT INTO tickets (ticket_id, product_name, price, tax, amount) VALUES (@ticket_id, @product_name, @price, @tax, @amount),然后在您的 SQL 命令对象上,对所有参数执行 sqlCommand.Parameters.Add("@ticket_id", ticket_id); sqlCommand.Parameters.Add("@product_name", pro2.ProductName); ...
【解决方案2】:

改用参数化查询。它使您免于注入攻击,并且实际上比使用硬编码值传递直接 SQL 更快(因为服务器可以缓存已编译的参数化查询并仅发送值)。这就是你的做法:

string query = "INSERT INTO ticket_elements " +
"(ticket_id, product_name, price, tax, amount) " +
"VALUES (@ticket_id, @product_name, @price, @tax, @amount);" + 
"SELECT SCOPE_IDENTITY();",
// Instantiate SqlCommand object with above query.
sqlCommand.Parameters.Add("@ticket_id", ticket_id);
sqlCommand.Parameters.Add("@product_name", pro2.ProductName);
sqlCommand.Parameters.Add("@price", tPrice);
sqlCommand.Parameters.Add("@tax", tax);
sqlCommand.Parameters.Add("@amount", fixedAmountStr);

请注意,如果您传入一个字符串,它将必须在 DB 端执行转换,如果无法转换它可能会失败。更好的做法是获取强类型值(换句话说,解析金额以确保它们有效),然后将这些值传递给参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多