Grz*_*lik 130
是的:).试试这个:
DECLARE @text AS NVARCHAR(10)
SET @text = '100'
SELECT CASE WHEN ISNUMERIC(@text) = 1 THEN CAST(@text AS INT) ELSE NULL END
-- returns 100
SET @text = 'XXX'
SELECT CASE WHEN ISNUMERIC(@text) = 1 THEN CAST(@text AS INT) ELSE NULL END
-- returns NULL
Run Code Online (Sandbox Code Playgroud)
ISNUMERIC()有一些问题由Fedor Hajdu指出.
喜欢它返回的字符串真$(是货币),,或.(两者都是分隔符),+和-.
Jos*_*ant 62
创建用户定义的函数.这将避免Fedor Hajdu在货币,分数等方面提到的问题:
CREATE FUNCTION dbo.TryConvertInt(@Value varchar(18))
RETURNS int
AS
BEGIN
SET @Value = REPLACE(@Value, ',', '')
IF ISNUMERIC(@Value + 'e0') = 0 RETURN NULL
IF ( CHARINDEX('.', @Value) > 0 AND CONVERT(bigint, PARSENAME(@Value, 1)) <> 0 ) RETURN NULL
DECLARE @I bigint =
CASE
WHEN CHARINDEX('.', @Value) > 0 THEN CONVERT(bigint, PARSENAME(@Value, 2))
ELSE CONVERT(bigint, @Value)
END
IF ABS(@I) > 2147483647 RETURN NULL
RETURN @I
END
GO
-- Testing
DECLARE @Test TABLE(Value nvarchar(50)) -- Result
INSERT INTO @Test SELECT '1234' -- 1234
INSERT INTO @Test SELECT '1,234' -- 1234
INSERT INTO @Test SELECT '1234.0' -- 1234
INSERT INTO @Test SELECT '-1234' -- -1234
INSERT INTO @Test SELECT '$1234' -- NULL
INSERT INTO @Test SELECT '1234e10' -- NULL
INSERT INTO @Test SELECT '1234 5678' -- NULL
INSERT INTO @Test SELECT '123-456' -- NULL
INSERT INTO @Test SELECT '1234.5' -- NULL
INSERT INTO @Test SELECT '123456789000000' -- NULL
INSERT INTO @Test SELECT 'N/A' -- NULL
SELECT Value, dbo.TryConvertInt(Value) FROM @Test
Run Code Online (Sandbox Code Playgroud)
参考:我在创建解决方案时广泛使用了此页面.
Fed*_*jdu 14
我宁愿创建一个像TryParse这样的函数,也可以使用T-SQL TRY-CATCH块来获得你想要的东西.
ISNUMERIC并不总是按预期工作.如果你这样做,之前给出的代码将失败:
SET @text ='$'
$ sign可以转换为money数据类型,因此ISNUMERIC()在这种情况下返回true.它将对' - '(减号),','(逗号)和'.'执行相同的操作.字符.
Dou*_*las 11
如前所述,如果您使用ISNUMERIC以下内容,可能会遇到几个问题:
-- Incorrectly gives 0:
SELECT CASE WHEN ISNUMERIC('-') = 1 THEN CAST('-' AS INT) END
-- Error (conversion failure):
SELECT CASE WHEN ISNUMERIC('$') = 1 THEN CAST('$' AS INT) END
SELECT CASE WHEN ISNUMERIC('4.4') = 1 THEN CAST('4.4' AS INT) END
SELECT CASE WHEN ISNUMERIC('1,300') = 1 THEN CAST('1,300' AS INT) END
-- Error (overflow):
SELECT CASE WHEN ISNUMERIC('9999999999') = 1 THEN CAST('9999999999' AS INT) END
Run Code Online (Sandbox Code Playgroud)
如果您想要可靠的转换,则需要自己编写代码.
更新:我的新建议是使用中间测试转换FLOAT来验证号码.这种方法基于adrianm的评论.逻辑可以定义为内联表值函数:
CREATE FUNCTION TryConvertInt (@text NVARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
SELECT
CASE WHEN ISNUMERIC(@text + '.e0') = 1 THEN
CASE WHEN CONVERT(FLOAT, @text) BETWEEN -2147483648 AND 2147483647
THEN CONVERT(INT, @text)
END
END AS [Result]
)
Run Code Online (Sandbox Code Playgroud)
一些测试:
SELECT [Conversion].[Result]
FROM ( VALUES
( '1234' ) -- 1234
, ( '1,234' ) -- NULL
, ( '1234.0' ) -- NULL
, ( '-1234' ) -- -1234
, ( '$1234' ) -- NULL
, ( '1234e10' ) -- NULL
, ( '1234 5678' ) -- NULL
, ( '123-456' ) -- NULL
, ( '1234.5' ) -- NULL
, ( '123456789000000' ) -- NULL
, ( 'N/A' ) -- NULL
, ( '-' ) -- NULL
, ( '$' ) -- NULL
, ( '4.4' ) -- NULL
, ( '1,300' ) -- NULL
, ( '9999999999' ) -- NULL
, ( '00000000000000001234' ) -- 1234
, ( '212110090000000235698741' ) -- NULL
) AS [Source] ([Text])
OUTER APPLY TryConvertInt ([Source].[Text]) AS [Conversion]
Run Code Online (Sandbox Code Playgroud)
结果类似于Joseph Sturtevant的答案,主要区别如下:
.或,为了模仿原生INT转换的行为.'1,234'并'1234.0'返回NULL.'00000000000000001234'评估为12.增加参数长度会导致溢出的数字出错BIGINT,例如BBAN(基本银行帐号)'212110090000000235698741'.撤回:不再推荐以下方法,仅供参考.
下面的代码段适用于非负整数.它检查您的字符串是否包含任何非数字字符,不为空,并且不会溢出(超过该int类型的最大值).但是,NULL由于前导零,它还提供长度超过10个字符的有效整数.
SELECT
CASE WHEN @text NOT LIKE '%[^0-9]%' THEN
CASE WHEN LEN(@text) BETWEEN 1 AND 9
OR LEN(@text) = 10 AND @text <= '2147483647'
THEN CAST (@text AS INT)
END
END
Run Code Online (Sandbox Code Playgroud)
如果要支持任意数量的前导零,请使用以下内容.嵌套CASE语句虽然不实用,但仍需要促进短路评估并降低错误的可能性(例如,由于将负长度传递给LEFT).
SELECT
CASE WHEN @text NOT LIKE '%[^0-9]%' THEN
CASE WHEN LEN(@text) BETWEEN 1 AND 9 THEN CAST (@text AS INT)
WHEN LEN(@text) >= 10 THEN
CASE WHEN LEFT(@text, LEN(@text) - 10) NOT LIKE '%[^0]%'
AND RIGHT(@text, 10) <= '2147483647'
THEN CAST (@text AS INT)
END
END
END
Run Code Online (Sandbox Code Playgroud)
如果你想支持正和负整数与任意数量的前导零的:
SELECT
-- Positive integers (or 0):
CASE WHEN @text NOT LIKE '%[^0-9]%' THEN
CASE WHEN LEN(@text) BETWEEN 1 AND 9 THEN CAST (@text AS INT)
WHEN LEN(@text) >= 10 THEN
CASE WHEN LEFT(@text, LEN(@text) - 10) NOT LIKE '%[^0]%'
AND RIGHT(@text, 10) <= '2147483647'
THEN CAST (@text AS INT)
END
END
-- Negative integers:
WHEN LEFT(@text, 1) = '-' THEN
CASE WHEN RIGHT(@text, LEN(@text) - 1) NOT LIKE '%[^0-9]%' THEN
CASE WHEN LEN(@text) BETWEEN 2 AND 10 THEN CAST (@text AS INT)
WHEN LEN(@text) >= 11 THEN
CASE WHEN SUBSTRING(@text, 2, LEN(@text) - 11) NOT LIKE '%[^0]%'
AND RIGHT(@text, 10) <= '2147483648'
THEN CAST (@text AS INT)
END
END
END
END
Run Code Online (Sandbox Code Playgroud)