2016-11-09 65 views
1

これは質問か他のSQL Serverユーザーの警告であるかわかりません。SQL ServerのISNUMERIC関数(マイナス記号のみ)

SQL ServerのISNUMERIC関数を使用して、文字列が数値かどうかを判断します。しかし今日、私たちは、ユーザーが文字列としてマイナス記号を渡したという問題がありました。

SQL ServerのISNUMERICは、この文字列に対して1を返し、数値であることを示します。 CASTこの文字列をintに変換します(値は0にキャストされます)。数値にキャストすると失敗します。

DECLARE @str NVARCHAR(200) 

SET @str = '-' 

-- This returns 1 (i.e. this string IS a number) 
SELECT ISNUMERIC(@str) 

-- This works (and returns 0) 
SELECT CAST(@str as int)     

-- This throws an error of "Arithmetic overflow error converting nvarchar to data type numeric." 
SELECT CAST(@str as numeric(12, 0))  

-- This throws an error of "Arithmetic overflow error converting nvarchar to data type numeric." 
SELECT CAST(@str as numeric(12, 7)) 

これが起こりそうな奇妙なケースはありますか?

+0

私の一般的な感想:データがSQL Serverに入る前に '-'を' -1'に置き換えてください。これはビジネスロジックであり、おそらくあなたのアプリケーション層で役立つでしょう。 –

+2

select isnumeric( '3.141e-09') - たとえば!あなたのニーズを正確に満たすためにLIKEで使用できる正規表現を試してみてください。ISNUMERICには多少の欠陥があります(私の例は有効な数字ですが) – Cato

+1

'ISNUMERIC'は誰も尋ねたくない質問に答えます。 *数値データ型の* any *に変換されています(私はどちらを気にしないのですか)? " –

答えて

2

あなたは簡単なチェックすることができます:回避策の一つはNOT LIKE '%[^0-9]%'

を使用することです

$ 
+ 
, 
- 
. 
\ 
€ 
¤ 

:これは数字が有効な数値型と見なされないだけことが表示されます

;WITH cte AS (
SELECT 1 as num 
UNION ALL 
SELECT num+1 
FROM cte 
WHERE num< 256 
) 

SELECT num, 
     CHAR(num), 
     ISNUMERIC(CHAR(num)) 
FROM cte 
WHERE ISNUMERIC(CHAR(num)) = 1 
OPTION (MAXRECURSION 1000) 

Fe私は、クエリ以下のWHEREステートメントにこのnd CHAR(num) NOT LIKE '%[^0-9]%'を追加する場合には、0から9

に番号を返すかTRY_PARSE(.. as int)

いくつかのリンクを使用します。

+0

その2番目の(SqlServerCentral)リンクが私が探していたものでした。 ISNUMERICが喜んで数字であると報告する単一文字の奇妙なリスト...そうでないときは。さて、教訓を学んだ...私は数値にキャストする前にISNUMERICを使うことに頼るべきではありません。ありがとうございました ! –

+0

私の喜び! :) – gofr1

0

ここでは置換可能なユーザー関数があります - 整数のみを受け付けます - 最大整数サイズの制限(もちろんBIGINTの場合)によって変換が保証されません。-1は受け付けますが、拒否します。

-- ================================================ 
-- Template generated from Template Explorer using: 
-- Create Scalar Function (New Menu).SQL 
-- 
-- Use the Specify Values for Template Parameters 
-- command (Ctrl-Shift-M) to fill in the parameter 
-- values below. 
-- 
-- This block of comments will not be included in 
-- the definition of the function. 
-- ================================================ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
-- ============================================= 
-- Author:  <Author,,Name> 
-- Create date: <Create Date, ,> 
-- Description: <Description, ,> 
-- ============================================= 
CREATE FUNCTION ISINTEGER 
(
    -- Add the parameters for the function here 
    @SINT nvarchar(20) 
) 
RETURNS int 
AS 
BEGIN 

    IF LEN(@SINT) = 0 
     RETURN 0; 

    IF LEFT(@SINT, 1) IN('+', '-') AND LEN(@SINT) > 1 
     RETURN CASE WHEN SUBSTRING(@SINT, 2, 1) IN ('+', '-') THEN 
             0 
            ELSE 
             DBO.ISINTEGER(RIGHT(@SINT, LEN(@SINT) - 1)) 
            END;   

    RETURN CASE WHEN @SINT NOT LIKE '%[^0-9]%' THEN 1 ELSE 0 END; 

END 
GO 
関連する問題