我有以下代码将nvarchar转换为整数:
cast(@value as int)
然而,我无法控制参数@value,因此代码可能会失败。有没有办法在进行强制转换之前检查是否可以进行强制转换?
我有以下代码将nvarchar转换为整数:
cast(@value as int)
然而,我无法控制参数@value,因此代码可能会失败。有没有办法在进行强制转换之前检查是否可以进行强制转换?
在SQL Server 2012中,您可以使用新的TRY_CAST()函数。但是,对于SQL Server 2008,您可以使用ISNUMERIC()函数,并包含处理未通过该测试的值的代码。
我最近回答了一个关于这个问题的问题,使用ISNUMERIC
进行CAST
到一个INT
本身是行不通的。原因是,ISNUMERIC
对于非整数数字(例如1.5)返回true。
以下是有关此主题的最近答案:
https://stackoverflow.com/a/14692165/1073631
考虑添加使用CHARINDEX和ISNUMERIC进行附加检查,或者使用正则表达式来验证数据(我更喜欢后者)。
这里是一个演示,说明单独使用ISNUMERIC存在的问题。这里是一个使用正则表达式而不是ISNUMERIC的演示,可以正常工作。
DECLARE @Test nvarchar(10)
SET @Test = '1.5'
--Works
SELECT CASE WHEN @Test NOT LIKE '%[^0-9]%' THEN CAST(@Test as int) ELSE 0 END
-- Produces Error
SELECT CASE WHEN ISNUMERIC(@Test) = 1 THEN CAST(@Test as int) ELSE 0 END
祝你好运。
SELECT CASE WHEN 1 = ISNUMERIC(@value + '.0') THEN CAST(@value as int) ELSE 0 END
此方法利用了“ISNUMERIC”函数不允许两个句点的特性。但在SQL Server 2012及以上版本中,“TRY_CAST”函数是更好的解决方案。
select (case when isnumeric(val) = 1 and val not like '%e%' and val not like '%.%'
then cast(val as int)
end)
isnumeric()
函数会对看起来像浮点数的任何内容返回1,因此您需要小心。
您还可以使用我认为是SQL Server的一个奇特之处。您可以将浮点值1.23强制转换为int类型,但无法将字符串值强制转换。因此,以下内容也有效:
select (case when isnumeric(val) = 1
then cast(cast(val as float) as int)
end)
isnumeric('+') == 1
。isnumeric('-') == 1
。isnumeric
是一个可怕的实现,而他们的答案会让你面对多个边缘情况,在这些情况下 cast
到 int
尽管你进行了检查仍然失败。 - mattmc3float
将会失败。(^^不是我的踩 - 我更喜欢评论而不是声誉损失)。这个答案提供了一种使用 ISNUMERIC
的方法,实际上处理了边缘情况,并确保您有一个合适的 TRY_CAST
替代方案:https://dev59.com/xW855IYBdhLWcg3wIAga - mattmc3
declare @value as nvarchar(10) = 'A';
begin try
select cast(@value as int);
end try
begin catch
-- do something
end catch
CREATE PROCEDURE p_try_cast
@type nvarchar(MAX),
@value nvarchar(MAX)
AS
BEGIN
BEGIN TRY
DECLARE @sql varchar(MAX)
DECLARE @out_table TABLE(value varchar(MAX))
SET @sql = 'SELECT CONVERT(varchar(max), CAST(''' + @value + ''' AS ' + @type + '))'
INSERT @out_table
EXECUTE (@sql)
IF EXISTS ( SELECT 1 FROM @out_table WHERE value = @value)
RETURN 1
RETURN 0
END TRY
BEGIN CATCH
RETURN 0
END CATCH
END
GO
DECLARE @ret int
-- This returns 0 - Fail
EXEC @ret = p_try_cast 'integer', '1.5'
-- This returns 1 - Success
EXEC @ret = p_try_cast 'integer', '1.5'
-- This returns 0 - Fail
EXEC @ret = p_try_cast 'char(4)', 'HELLO'
-- This returns 1 - Success
EXEC @ret = p_try_cast 'char(4)', 'HELL'