我有一个简单的存储过程,其中target table和where子句条件被指定为参数。 “将nvarchar转换为数据类型数字的算术溢出错误”。错误让我有点沮丧。
@TableName varchar(50), -- 'A_RECORD_ETH0' test value
@Time_ms decimal(18,4), -- '40388629085.6481' test value
@Records int out, -- should result with '1' if test values are used
这有效:
SELECT COUNT(*) as Count FROM A_RECORD_ETH0 WHERE Time_ms = 40388629085.6481
这有效:
SET @sql = N'SET @Records = (SELECT COUNT(*) FROM A_RECORD_ETH0 WHERE Time_ms = 40388629085.6481 )'
EXEC sp_executesql @sql, N'@Records int output', @Records output
这有效:
SET @sql = N'SET @Records = (SELECT COUNT(*) FROM '+ @TableName + ' WHERE Time_ms = 40388629085.6481 )'
EXEC sp_executesql @sql, N'@Records int output', @Records output
这会导致算术溢出错误:
SET @sql = N'SET @Records = (SELECT COUNT(*) FROM '+ @TableName + ' WHERE Time_ms = ' + @Time_ms + ' )'
EXEC sp_executesql @sql, N'@Records int output', @Records output
即使使用强制转换,也会导致算术溢出错误:
SET @sql = N'SET @Records = (SELECT COUNT(*) FROM '+ @TableName + ' WHERE Time_ms = Cast ( ' + @Time_ms + ' as decimal(18,4)) )'
EXEC sp_executesql @sql, N'@Records int output', @Records output
答案 0 :(得分:1)
直接传递@Time_ms可避免使用decimal-> string->十进制转换。它也更有效率;当@Time_ms改变时,服务器仍然可以重用执行计划而不是生成新计划。
SET @sql = N'SET @Records = (SELECT COUNT(*) FROM '+ @TableName + ' WHERE Time_ms = @Time_ms'
EXEC sp_executesql @sql, N'@Time_ms decimal(18,4), @Records int output', @Time_ms=@Time_ms, @Records output
答案 1 :(得分:0)
我根据您的代码完成了以下工作:
DECLARE @sqlSelect nvarchar(500);
DECLARE @ParmSelect nvarchar(500);
SET @sqlSelect = N'SET @RecordsOut = (SELECT COUNT(*) FROM ' + @TableName + ' WHERE Time_ms = @Time_msIn)'
SET @ParmSelect = N'@Time_msIn decimal(18,4), @RecordsOut int OUTPUT';
EXEC sp_executesql @sqlSelect, @ParmSelect, @Time_msIn = @Time_ms, @RecordsOut = @Records OUTPUT;