我正在使用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年。
答案 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轮的值为零。