我的报告已经使用了很长时间 - 实际上,公司的发票系统在很大程度上依赖于此报告(免责声明:我没有写过)。过滤基于VarChar(50)类型的字段是否落在用户传入的两个数值之间。
问题在于,现在过滤数据的字段不仅具有简单的非数字值,例如'/ A','TEST'和一系列其他非数字数据,而且还具有数值似乎在藐视我能想到的任何类型的数字转换。
以下(简化)测试查询演示了失败:
Declare @StartSummary Int,
@EndSummary Int
Select @StartSummary = 166285,
@EndSummary = 166289
Select SummaryInvoice
From Invoice
Where IsNull(SummaryInvoice, '') <> ''
And IsNumeric(SummaryInvoice) = 1
And Convert(int, SummaryInvoice) Between @StartSummary And @EndSummary
我还尝试使用bigint,real和float进行转换,所有这些都给了我类似的错误:
Msg 8115,Level 16,State 2,Line 7 算术溢出错误转换 表达式到数据类型int。
我尝试过其他较大的数值数据类型,例如BigInt,但错误相同。我还尝试使用子查询来回避转换问题,只提取具有数字数据的字段,然后在包装器查询中转换它们,但随后我得到其他错误,这些错误都是主题上的所有变体,表明存储的值SummaryInvoice字段无法转换为相关数据类型。
如果没有将具有数字SummaryInvoice字段的记录提取到临时表然后查询临时表,是否有任何一步解决方案可以解决此问题?
修改:这是我怀疑导致问题的字段数据:
SummaryInvoice
11111111111111111111111111
IsNumeric声明此字段为数字 - 。但是尝试将其转换为BigInt会导致算术溢出。有任何想法吗?它似乎不是一个孤立的事件,似乎有许多记录填充了导致此问题的数据。
答案 0 :(得分:3)
似乎你会遇到ISNUMERIC
函数的问题,因为如果可以转换为任何数字类型,它会返回1(包括.
,,
,{{1}等等)。如果您的号码长于2 ^ 63-1,则可以使用e0
或DECIMAL
。我不确定您是否可以使用NUMERIC
在PATINDEX
上执行正则表达式查看,但如果可以的话,那么您应该尝试一下:
SummaryInvoice
答案 1 :(得分:1)
您无法保证将应用WHERE子句过滤器的顺序。
解除内在和外在的一个丑陋的选择。
SELECT
*
FROM
(
Select TOP 2000000000
SummaryInvoice
From Invoice
Where IsNull(SummaryInvoice, '') <> ''
And IsNumeric(SummaryInvoice) = 1
ORDER BY SummaryInvoice
) foo
WHERE
Convert(int, SummaryInvoice) Between @StartSummary And @EndSummary
另一个使用CASE
Select SummaryInvoice
From Invoice
Where IsNull(SummaryInvoice, '') <> ''
And
CASE WHEN IsNumeric(SummaryInvoice) = 1 THEN Convert(int, SummaryInvoice) ELSE -1 END
Between @StartSummary And @EndSummary
YMMV
编辑:问题更新后
答案 2 :(得分:0)
AND与IsNumeric(SummaryInvoice)= 1,不会在SQL Server中短路。
但可能你可以使用
AND(CASE IsNumeric(SummaryInvoice)= 1那么转换(int,SummaryInvoice)ELSE 0 END) 在@StartSummary和@EndSummary之间
答案 3 :(得分:0)
您的第一个问题是修复您的数据库结构,以便糟糕的数据无法进入该字段。你正在为需要缝合的伤口放一个创可贴,并想知道它为什么不愈合。
数据库重构并不好玩,但需要在出现数据完整性问题时完成。我假设你不是真的为11,111,111,111,111,111,111,111,111或'test'开具发票。因此,不要允许输入这些值(如果您不能将结构更改为正确的数据类型,请考虑触发以防止错误数据进入)并删除您确实存在的错误数据。