如果我有一个参数化的存储过程,该过程接受varchar(10)值并将其转换为int,我当前必须确保该值不大于最大int值的varchar等值。
IF @Criteria <= '2147483647'
SET @Id = CONVERT(int, @Criteria)
我的问题:从varchar值转换时,是否有更好的方法可以防止溢出int列?
编辑:是的,如果我觉得该值合法地包含接近最大值的值,我可以扩展到BigInt。这实际上意味着处理对此存储过程的不正确调用,并且只是在结果值可能溢出所需数据类型的情况下使用Convert()的一般目的问题。
答案 0 :(得分:3)
要处理各种条件(空格,小数等),如果无法在客户端上清理,请将转换包装在TRY / CATCH中。假设SQL Server 2005
...
BEGIN TRY
SET @Id = CONVERT(int, @Criteria)
END TRY
BEGIN CATCH
SET @Id = NULL
END CATCH
...
答案 1 :(得分:3)
您的测试无法可靠地运行。
如果@Criteria包含'11111111111111111111',它的排序小于您的幻数,因为您正在进行字符串比较。
答案 2 :(得分:1)
最简单,最好的方法是在源处理它,即创建varchar的地方。或者用“防止溢出”来解释你的意思。当varchar实际上太长时,您期望发生什么?
答案 3 :(得分:1)
如果你进入空间怎么办? - 它将通过IF条件但转换失败。你也应该使用ISNUMERIC()。
IF @Criteria <= '2147483647' AND ISNUMERIC(@Criteria)
SET @Id = CONVERT(int, @Criteria)
答案 4 :(得分:1)
更好的问题可能就是为什么要存储溢出其目标列的整数作为varchars。我不太清楚你能做些什么来完全防止溢出;您可以考虑将Id切换为无符号整数,因此您可以获得最多2 ^ 32位可用(我猜测Criteria永远不会为负,因为您将其分配给Id列。)
我不确定SQL Server是否支持它,但MySQL有BIGINT列,最多可达2 ^ 64(如果你想签名,则为2 ^ 63)。
答案 5 :(得分:1)
首先,您的输入长度10看起来像您不期望(或接受)负值。 int的下限是-2147483648,它将由一个11个字符的字符串表示。
基于上面的DJ代码,我建议你在CONVERT / compare之前调用ISNUMERIC()。
IF ISNUMERIC(@Criteria) = 1
AND CONVERT(bigint, @Criteria) <= 2147483647
SET @Id = CONVERT(int, @Criteria)
首先转换为bigint,然后进行比较。以下是一些测试用例:
DECLARE @Id int
DECLARE @Criteria varchar(10)
PRINT 'Expect failure (NULL)'
SET @Criteria = '2147483648'
SET @Id = NULL
IF ISNUMERIC(@Criteria) = 1
AND CONVERT(bigint, @Criteria) <= 2147483647
SET @Id = CONVERT(int, @Criteria)
SELECT @Id AS '@Id', @Criteria AS '@Criteria', CONVERT(bigint, @Criteria) AS 'Converted to bigint'
PRINT 'Expect success'
SET @Criteria = '2147483647'
SET @Id = NULL
IF ISNUMERIC(@Criteria) = 1
AND CONVERT(bigint, @Criteria) <= 2147483647
SET @Id = CONVERT(int, @Criteria)
SELECT @Id AS '@Id', @Criteria AS '@Criteria', CONVERT(bigint, @Criteria) AS 'Converted to bigint'
PRINT 'Expect failure but get success because @Criteria is truncated to 10 characters'
SET @Criteria = '11111111111111111111'
SET @Id = NULL
IF ISNUMERIC(@Criteria) = 1
AND CONVERT(bigint, @Criteria) <= 2147483647
SET @Id = CONVERT(int, @Criteria)
SELECT @Id AS '@Id', @Criteria AS '@Criteria', CONVERT(bigint, @Criteria) AS 'Converted to bigint'
和结果:
Expect failure (NULL)
@Id @Criteria Converted to bigint
----------- ---------- --------------------
NULL 2147483648 2147483648
Expect success
@Id @Criteria Converted to bigint
----------- ---------- --------------------
2147483647 2147483647 2147483647
Expect failure but get success because @Criteria is truncated to 10 characters
@Id @Criteria Converted to bigint
----------- ---------- --------------------
1111111111 1111111111 1111111111
请注意,传递'11111111111111111111'实际上是有效的,因为输入被截断了。