2013-02-06 131 views

回答

21

那么,在SQL Server 2012中,您可以使用新的TRY_CAST(),但对于SQL Server 2008,您应该能够使用ISNUMERIC(),然后包含对未通过该测试的值的处理。

+5

-1:select isnumeric('1.');选择投射('1。'int); – Pete

+0

ISNumeric('a1a')返回1,但是你永远不能投('a1a'为float) – CodingTT

+0

我相信你的意思是SQL Server 2014:https://msdn.microsoft.com/en-us/library/hh974669.aspx –

10

我最近回答了一个关于这个问题,并使用ISNUMERICCASTINT不会自行工作。原因在于,例如,ISNUMERIC对非整数(1.5)返回true。

这里是关于这个问题的答案最近:

https://stackoverflow.com/a/14692165/1073631

考虑增加使用CHARINDEX与ISNUMERIC额外的检查,或者是我愿意的话,使用正则表达式来验证数据。

这里是一个Fiddle演示自己使用ISNUMERIC的问题。而Fiddle使用正则表达式代替它的作用。

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 

祝你好运。

+0

+1。 。 。第一个是正确的。你的答案应该更清楚一点,第二个是错误的(我必须滚动才能看到“产生错误”)。 –

+0

你也应该防范溢出(并可选择允许负整数):http://stackoverflow.com/a/24250511/1149773 – Douglas

0

适当的测试是:

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) 
+1

不,这是错误的。 'isnumeric('+')== 1'。 'isnumeric(' - ')== 1'。 'isnumeric'是一个可怕的实现,他们的回答让你开放到多个边缘情况下,尽管你检查了'cast'到'int'将会失败。 – mattmc3

+0

@ mattmc3。 。你有没有注意到OP基本接受了这个答案。另外,转换为'float'可以修复许多这些问题(尽管不会溢出)。 –

+0

接受的答案获取SQL 2012+的TRY_CAST部分。要使用ISNUMERIC,你必须做很多体操来处理边缘情况。例如,将“+”或“ - ”作为“val”的值插入。对'浮动'的演员阵容将会非常壮观。 (^^不是我的downvote顺便说一句 - 我更喜欢评论来表示伤害)。这个答案给出了一种使用'ISNUMERIC'来实际处理边界情况并确保你有一个正确的'TRY_CAST'替代方法:http://stackoverflow.com/questions/4522056/how-to-determine-the-field-value -which-can-not-convert-to-decimal-float-int-i – mattmc3

1

也许我们可以做这样的事情:

declare @value as nvarchar(10) = 'A'; 

begin try 
    select cast(@value as int); 
end try 
begin catch 
-- do something 
end catch 
+0

我喜欢这种方法,但是我们不能在SELECT语句中做到这一点,我们可以吗? –

2

我一般采用下面,似乎涵盖所有的情况。

SELECT CASE WHEN 1 = ISNUMERIC(@value + '.0') THEN CAST(@value as int) ELSE 0 END 

它利用了“ISNUMERIC”不允许两个周期的事实。尽管SQL Server 2012+中的“TRY_CAST”是一个更好的解决方案。

0

使用过程用try 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 

现在你可以调用与传递的字符串和所需类型和proc的失败则返回1成功和0

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' 
相关问题