为什么在将带有varchar参数的c#double传递给SQL过程时会丢失精度?

时间:2015-03-18 16:30:11

标签: sql-server string type-conversion double varchar

我正在使用SQL Server存储过程,其中包含一个字符串作为参数。预计字符串将代表一个数字。通常,我会为此使用数字类型,但此过程会执行一些要求它为数字的内容。

我遇到了四舍五入的问题。为了简化问题,我写了这个程序:

CREATE PROCEDURE dbo.TestProc @s 
    VARCHAR(20)  
AS
    SELECT @s;

我从C#代码中调用此过程如下。

var cmd = new SqlCommand()
{
    CommandText = "TestProc",
    CommandType = CommandType.StoredProcedure,
    Connection = myConnection
};

cmd.Parameters.Add(new SqlParameter("@s", -157.7181));

var reader = cmd.ExecuteReader();

reader.Read();

// Should get -157.7181, but get -157.718 instead
var x = reader[0];

结果是万分之一。

但是,当我使用下面的代码添加参数时,我得到了正确的结果。

cmd.Parameters.Add(new SqlParameter("@s", "-157.7181"));

换句话说,在c#中使用字符串显示数字会产生正确的答案,同时允许将其转换为字符串会隐式创建舍入错误。

我可以很容易地看到我的问题的解决方案是在添加参数之前将我的double值显式地转换为字符串,但我的问题是:为什么?

如何解释?

我的Visual Studio版本和SQL Server版本都是2008年。

1 个答案:

答案 0 :(得分:0)

从浮点值转换为字符串时,看起来像是SQL的默认行为。看看这个:

declare @f float = 157.7181
select @f, convert(varchar(20), @f), STR(@f, 18, 10)

导致:

(No column name)    (No column name)    (No column name)
157.7181            157.718             157.7181000000

从Transact-SQL手册(https://msdn.microsoft.com/en-us/library/ms173773.aspx):

当转换为任何整数类型时,float的值将被截断。 当您想要从float或real转换为字符数据时,使用STR字符串函数通常比CAST()更有用。这是因为STR可以更好地控制格式。有关更多信息,请参阅STR(Transact-SQL)和内置函数(Transact-SQL)。 将使用科学记数法的浮点值转换为十进制或数字仅限于精度为17位的值。任何精度高于17轮的值为零。