これは、例外をスローすることなく、すべてのケースを処理する必要があります。
--This handles dollar-signs, commas, decimal-points, and values too big or small,
-- all while safely returning an int.
DECLARE @IntString as VarChar(50) = '$1,000.'
SELECT CAST((CASE WHEN --This IsNumeric check here does most of the heavy lifting. The rest is Integer-Specific
ISNUMERIC(@IntString) = 1
--Only allow Int-related characters. This will exclude things like 'e' and other foreign currency characters.
AND @IntString NOT LIKE '%[^ $,.\-+0-9]%' ESCAPE '\'--'
--Checks that the value is not out of bounds for an Integer.
AND CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(38)) BETWEEN -2147483648 AND 2147483647
--This allows values with decimal-points for count as an Int, so long as there it is not a fractional value.
AND CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(38)) = CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(38,2))
--This will safely convert values with decimal points to casting later as an Int.
THEN CAST(REPLACE(REPLACE(@IntString,'$',''),',','') as Decimal(10))
END) as Int)[Integer]
これを Scalar UDF にスローし、それをReturnInt()と呼びます。
値が NULL として返される場合、それは int ではありません (したがって、IsInteger() 要件があります)。
「 WHERE ReturnInt(SomeValue) IS NOT NULL 」と入力したくない場合は、それをIsInt()という別のスカラー UDF にスローして、この関数を呼び出し、単純に「ReturnInt(SomeValue) IS NOT NULL」を返すことができます。
すばらしいことに、UDF は "安全に" 変換された int 値
を返すことで、2 つの役割を果たします。
何かが int になる可能性があるからといって、それを int としてキャストしても大きな例外がスローされないわけではありません。これはあなたのためにそれを処理します。
また、この普遍的なアプローチはコンマ、小数、ドル記号を処理し、許容可能な Int 値の範囲をチェックしますが、他のソリューションは処理しないため、他のソリューションは避けます。または、ロジックを使用できないようにする複数の SET 操作が必要です。最大のパフォーマンスのためのスカラー関数。
以下の例を参照して、私のコードや他のコードに対してテストしてください。
--Proves that appending "e0" or ".0e0" is NOT a good idea.
select ISNUMERIC('$1' + 'e0')--Returns: 0.
select ISNUMERIC('1,000' + 'e0')--Returns: 0.
select ISNUMERIC('1.0' + '.0e0')--Returns: 0.
--While these are numeric, they WILL break your code
-- if you try to cast them directly as int.
select ISNUMERIC('1,000')--Returns: 1.
select CAST('1,000' as Int)--Will throw exception.
select ISNUMERIC('$1')--Returns: 1.
select CAST('$1' as Int)--Will throw exception.
select ISNUMERIC('10.0')--Returns: 1.
select CAST('10.0' as Int)--Will throw exception.
select ISNUMERIC('9999999999223372036854775807')--Returns: 1. This is why I use Decimal(38) as Decimal defaults to Decimal(18).
select CAST('9999999999223372036854775807' as Int)--Will throw exception.
更新:
「123」のような値を解析できるようにしたいというコメントをここで読みました。整数に。これも処理するようにコードを更新しました。
注:これは "1.0" を変換しますが、"1.9" では null を返します。
丸めを許可する場合は、"THEN" 句のロジックを微調整して、次のように Round() を追加します。
ROUND(CAST(REPLACE(REPLACE(@IntString,'$',''),',',') ') as Decimal(10)), 0)
丸めまたは切り捨てを可能にするために、「小数点」をチェックする「AND」も削除する必要
があります。