SQL 服务器浮动数据类型超出范围
SQL Server Float Datatype out of range
我有一个通过扩展事件会话捕获的查询,其浮点数据类型如下所示:
@variable = 120700.8000000000000000000000000000000000000000000000
如果我尝试 运行 在 SSMS 中执行相同的查询,我会收到错误消息:
数字“120700.8000000000000000000000000000000000000000000000”超出数值表示范围(最大精度 38)。
就好像你要 运行
DECLARE @variable float = 120700.8000000000000000000000000000000000000000000000
跟踪为 运行ning 时查询成功。事件是 rpc_completed,它有持续时间、cpu、行数等...
不确定这是否相关,但有问题的查询是一个 exec sp_executeSQL。跟踪捕获的完整查询如下所示:
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > @variable', N'@variable float',
@variable = 120700.8000000000000000000000000000000000000000000000
所以我的问题是,为什么跟踪中的代码能够无误地执行,但是当我 copy/paste 将相同的代码发送到 SSMS 时它会抛出错误。如果我使用相同的代码并 trim 去掉一堆零,它就可以工作了。
我正在 运行宁 SQL Azure DB。我在兼容性 SQL2016、SQL2019 和 Prem SQL2019.
上进行了转载
字符串文字 120700.8000000000000000000000000000000000000000000000
首先被隐式转换为十进制,因此出现错误。
尝试
DECLARE @variable float = 120700.8000000000000000000000000000000000000000000000E0
来源:TSQL - make a literal float value
why is the code in the trace able to execute without error, but when I
copy/paste that same code to SSMS it throws an error.
当您将此查询放入 SSMS 时
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > @variable', N'@variable float',
@variable = 120700.8000000000000000000000000000000000000000000000
文字 120700.8000000000000000000000000000000000000000000000
被解释为 numeric/decimal 类型。引擎尝试将其转换为 numeric/decimal 类型的值但失败了,因为数字的最大精度为 38 位。
如果将此查询放在 SSMS 中,它应该可以工作
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > @variable', N'@variable float',
@variable = 120700.8000000000000000000000000000000000000000000000E0
我在最后添加了E0
。
要生成 float
文字,我们需要使用科学记数法,如 Constants (Transact-SQL)
中所述
why is the code in the trace able to execute without error
我不能肯定地说,但我怀疑您在跟踪中看到的代码与应用程序发送到 SQL 服务器的代码不完全相同。它可能以这样一种方式发送,即参数类型和值实际上是 float
,而不是包含所有这些零的文本字符串。
我认为,应用程序很可能会进行 RPC 调用,将具有正确类型的正确参数传递给函数调用。因此,当应用程序成功调用时,从来没有从文本字符串转换为 numeric
或 float
类型。
关于我为证明上面接受的答案所做的工作的详细信息。
我正在使用 trace 语句并使用 C# 在另一个数据库上重播它(这将引发超出范围的错误):
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "exec sp_executesql @stmt=N'SELECT @f',
@params=N'@f float',@f=120700.800000000002910383045673370361328125";
cmd.ExecuteNonQuery();
我需要做的是提取这些部分并构建一个具有如下参数的存储过程:
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "sp_executesql";
SqlParameter p1 = new SqlParameter();
p1.DbType = System.Data.DbType.String;
p1.ParameterName = "@stmt";
p1.Value = "SELECT @f";
SqlParameter p2 = new SqlParameter();
p2.DbType = System.Data.DbType.String;
p2.ParameterName = "@params";
p2.Value = "@f float";
SqlParameter p3 = new SqlParameter();
p3.DbType = System.Data.DbType.Double;
p3.Value = 120700.8000000000000000000000000000000000000000000000;
p3.ParameterName = "@f";
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
cmd.Parameters.Add(p3);
cmd.ExecuteNonQuery();
当我 运行 时,它在跟踪中显示为:
exec sp_executesql @stmt=N'SELECT @f',@params=N'@f float',@f=120700.800000000002910383045673370361328125
所以问题是我不能只从 rpc_completed 事件中获取语句。我需要对其进行解析并显式重建存储过程。
我有一个通过扩展事件会话捕获的查询,其浮点数据类型如下所示:
@variable = 120700.8000000000000000000000000000000000000000000000
如果我尝试 运行 在 SSMS 中执行相同的查询,我会收到错误消息: 数字“120700.8000000000000000000000000000000000000000000000”超出数值表示范围(最大精度 38)。
就好像你要 运行
DECLARE @variable float = 120700.8000000000000000000000000000000000000000000000
跟踪为 运行ning 时查询成功。事件是 rpc_completed,它有持续时间、cpu、行数等...
不确定这是否相关,但有问题的查询是一个 exec sp_executeSQL。跟踪捕获的完整查询如下所示:
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > @variable', N'@variable float',
@variable = 120700.8000000000000000000000000000000000000000000000
所以我的问题是,为什么跟踪中的代码能够无误地执行,但是当我 copy/paste 将相同的代码发送到 SSMS 时它会抛出错误。如果我使用相同的代码并 trim 去掉一堆零,它就可以工作了。
我正在 运行宁 SQL Azure DB。我在兼容性 SQL2016、SQL2019 和 Prem SQL2019.
上进行了转载字符串文字 120700.8000000000000000000000000000000000000000000000
首先被隐式转换为十进制,因此出现错误。
尝试
DECLARE @variable float = 120700.8000000000000000000000000000000000000000000000E0
来源:TSQL - make a literal float value
why is the code in the trace able to execute without error, but when I copy/paste that same code to SSMS it throws an error.
当您将此查询放入 SSMS 时
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > @variable', N'@variable float',
@variable = 120700.8000000000000000000000000000000000000000000000
文字 120700.8000000000000000000000000000000000000000000000
被解释为 numeric/decimal 类型。引擎尝试将其转换为 numeric/decimal 类型的值但失败了,因为数字的最大精度为 38 位。
如果将此查询放在 SSMS 中,它应该可以工作
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > @variable', N'@variable float',
@variable = 120700.8000000000000000000000000000000000000000000000E0
我在最后添加了E0
。
要生成 float
文字,我们需要使用科学记数法,如 Constants (Transact-SQL)
why is the code in the trace able to execute without error
我不能肯定地说,但我怀疑您在跟踪中看到的代码与应用程序发送到 SQL 服务器的代码不完全相同。它可能以这样一种方式发送,即参数类型和值实际上是 float
,而不是包含所有这些零的文本字符串。
我认为,应用程序很可能会进行 RPC 调用,将具有正确类型的正确参数传递给函数调用。因此,当应用程序成功调用时,从来没有从文本字符串转换为 numeric
或 float
类型。
关于我为证明上面接受的答案所做的工作的详细信息。
我正在使用 trace 语句并使用 C# 在另一个数据库上重播它(这将引发超出范围的错误):
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "exec sp_executesql @stmt=N'SELECT @f',
@params=N'@f float',@f=120700.800000000002910383045673370361328125";
cmd.ExecuteNonQuery();
我需要做的是提取这些部分并构建一个具有如下参数的存储过程:
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "sp_executesql";
SqlParameter p1 = new SqlParameter();
p1.DbType = System.Data.DbType.String;
p1.ParameterName = "@stmt";
p1.Value = "SELECT @f";
SqlParameter p2 = new SqlParameter();
p2.DbType = System.Data.DbType.String;
p2.ParameterName = "@params";
p2.Value = "@f float";
SqlParameter p3 = new SqlParameter();
p3.DbType = System.Data.DbType.Double;
p3.Value = 120700.8000000000000000000000000000000000000000000000;
p3.ParameterName = "@f";
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
cmd.Parameters.Add(p3);
cmd.ExecuteNonQuery();
当我 运行 时,它在跟踪中显示为:
exec sp_executesql @stmt=N'SELECT @f',@params=N'@f float',@f=120700.800000000002910383045673370361328125
所以问题是我不能只从 rpc_completed 事件中获取语句。我需要对其进行解析并显式重建存储过程。