値が整数かどうか(.NETのTryParse
など)を判断したい。残念ながらISNUMERIC
は私には合いません。なぜなら、あらゆる種類の数値ではなく整数だけを解析したいからです。 ISINT
などのようなものはありますか?
わかりやすくするためのコードを次に示します。 MY_FIELD
はintではありません。このコードは失敗します:
SELECT @MY_VAR = CAST(MY_FIELD AS INT)
FROM MY_TABLE
WHERE MY_OTHER_FIELD = 'MY_FILTER'
ありがとうございました
これは ブログ投稿IsInteger
UDFの作成を説明しています。
基本的に、'.e0'
を値に追加し、IsNumeric
を使用することをお勧めします。この方法で、すでに小数点があったものはすべて2つの小数点を持ち、IsNumeric
が偽になり、科学表記法で既に表現されたものはe0
によって無効になります。
Itzik Ben-Ganは、彼の記事 この文字列を整数に変換できますか? で、純粋なT-SQLとCLRを使用する別のソリューションを提供しています。
どのソリューションを選択する必要がありますか?
T-SQLまたはCLRソリューションの方が優れていますか?T-SQLソリューションを使用する利点は、ドメイン外に移動する必要がないことです。 T-SQLプログラミング。ただし、CLRソリューションには2つの重要な利点があります。それは、よりシンプルで高速なことです。 1,000,000行のテーブルに対して両方のソリューションをテストした場合、CLRソリューションはラップトップで実行するのに(T-SQLソリューションの場合)7秒ではなく2秒かかりました。そのため、次に特定の文字列を整数に変換できるかどうかを確認する必要がある場合、この記事で提供したT-SQLまたはCLRソリューションを含めることができます。
T-SQLのみを管理する場合は、純粋なT-SQLソリューションを使用してください。利便性よりもパフォーマンスが重要な場合は、CLRソリューションを使用してください。
純粋なT-SQLソリューションには注意が必要です。組み込みのISNUMERIC関数とパターンマッチングおよびキャストを組み合わせて、文字列がintを表しているかどうかを確認します。
SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
CASE
WHEN ISNUMERIC(string) = 0 THEN 0
WHEN string LIKE '%[^-+ 0-9]%' THEN 0
WHEN CAST(string AS NUMERIC(38, 0))
NOT BETWEEN -2147483648. AND 2147483647. THEN 0
ELSE 1
END AS is_int
FROM dbo.T1;
CLRソリューションのT-SQL部分はよりシンプルです。 ISNUMERICを呼び出すのと同じように、fn_IsInt関数を呼び出します。
SELECT keycol, string, ISNUMERIC(string) AS is_numeric,
dbo.fn_IsInt(string) AS is_int
FROM dbo.T1;
C#部分は、.NETの解析関数Int32.TryParseの単なるラッパーです。これは、SQL Server intと.NET Int32の両方が32ビット符号付き整数であるため機能します。
using System;
using System.Data.SqlTypes;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean fn_IsInt(SqlString s)
{
if (s.IsNull)
return SqlBoolean.False;
else
{
Int32 i = 0;
return Int32.TryParse(s.Value, out i);
}
}
};
これらのコードサンプルの詳細については、Itzikの記事をご覧ください。
WHERE IsNumeric(MY_FIELD) = 1 AND CAST(MY_FIELD as VARCHAR(5)) NOT LIKE '%.%'
それがおそらく最も簡単なソリューションです。 MY_FIELD
には.00またはその種のものが含まれます。その場合、後続の.00を削除するためにフロートにキャストします
以下はWHERE
句に適しています。関数をCASE WHEN
でラップするようにします。
ISNUMERIC(table.field) > 0 AND PATINDEX('%[^0123456789]%', table.field) = 0
以下のクエリが役立つかどうかを確認してください
SELECT *
FROM MY_TABLE
WHERE CHARINDEX('.',MY_FIELD) = 0 AND CHARINDEX(',',MY_FIELD) = 0
AND ISNUMERIC(MY_FIELD) = 1 AND CONVERT(FLOAT,MY_FIELD) / 2147483647 <= 1
ネクロマンシング。
SQL-Server 2012+では、TRY_CASTを使用できます。TRY_CASTは、キャストが失敗した場合にNULLを返します。
例:
DECLARE @foo varchar(200)
SET @foo = '0123'
-- SET @foo = '-0123'
-- SET @foo = '+0123'
-- SET @foo = '+-0123'
-- SET @foo = '+-0123'
-- SET @foo = '.123'
-- SET @foo = '1.23'
-- SET @foo = '.'
-- SET @foo = '..'
-- SET @foo = '0123e10'
SELECT CASE WHEN TRY_CAST(@foo AS integer) IS NULL AND @foo IS NOT NULL THEN 0 ELSE 1 END AS isInteger
これが唯一の本当に信頼できる方法です。
SQL-Server 2008のサポートが必要な場合は、Sam DeHaanの答えに戻ってください。
SELECT CASE WHEN ISNUMERIC(@foo + '.e0') = 1 THEN 1 ELSE 0 END AS isInteger
SQL-Server <2012(別名2008R2)は、2019-07-09までに(拡張)サポートが終了します。
この時点で、非常にすぐに、<2012のサポートを終了できます。
この時点では、他のハックはもう使用しません。
更新するように質素な顧客に伝えてください-2008年から10年以上経過しています。
IsNumeric関数を使用したこの回避策は機能します。
iSNUMERIC(x)= 1のAから*を選択し、Xは '%。%'を好まない
または使用
select * from A where x not like '%[^ 0-9]%'
データベースの設計に何か問題があると思います。 varcharと数値を1つの列に混在させるのは本当に悪い考えだと思いますか?その理由は何ですか?
もちろん、[0-9]以外の文字があるかどうかを確認できますが、テーブルに1m行あり、すべての行をチェックしていると想像してください。うまくいかないと思います。
とにかく、本当にやりたいのなら、クライアント側でやることをお勧めします。
私はこのようにそれをすることは悪魔の仕事であると感じていますが、代替として:
TRY-キャッチはどうですか?
DECLARE @Converted as INT
DECLARE @IsNumeric BIT
BEGIN TRY
SET @Converted = cast(@ValueToCheck as int)
SET @IsNumeric=1
END TRY
BEGIN CATCH
SET @IsNumeric=0
END CATCH
select IIF(@IsNumeric=1,'Integer','Not integer') as IsInteger
これは機能しますが、SQL Server 2008以降でのみ機能します。
declare @i numeric(28,5)= 12.0001 if(@ i/cast(@i in int)> 1) begin select 'this is not int' end else begin select 'this is int' end
私はSQLのプロではありませんが、1で割り切れるかどうかをチェックするのはどうですか?私にとっては仕事をします。
SELECT *
FROM table
WHERE fieldname % 1 = 0
SQL Server 2012の時点で、TRY_CONVERT
およびTRY_CAST
関数が実装されました。これは、ISNUMERIC
ソリューションを大幅に改善したもので、偽陽性(または陰性)を引き起こす可能性があります(実際にそうします)。たとえば、以下を実行する場合:
SELECT CONVERT(int,V.S)
FROM (VALUES('1'),
('900'),
('hello'),
('12b'),
('1.1'),
('')) V(S)
WHERE ISNUMERIC(V.S) = 1;
TRY_CONVERT
(またはTRY_CAST
)を使用すると、次のことが回避されます。
SELECT TRY_CONVERT(int,V.S),
V.S,
ISNUMERIC(V.S)
FROM (VALUES('1'),
('900'),
('hello'),
('12b'),
('1.1'),
('')) V(S)
--WHERE TRY_CONVERT(int,V.S) IS NOT NULL; --To filter to only convertable values
'1.1'
がNULL
を返したため、以前にエラーが発生しました(10進数の文字列表現はint
に変換できないため)。また、''
が0
、たとえISNUMERIC
は値を「変換できません」と述べています。
データベースを設計できない場合があります。与えられたもので作業するだけです。私の場合、それは2008年以降に存在していた読み取りアクセス権しか持っていないコンピューター上のデータベースです。
設計が不十分なデータベースの列から選択する必要があります。このデータベースは、1〜100の数字を持つvarchar
ですが、時にはランダムな文字列です。私はそれを回避するために以下を使用しました(データベース全体を再設計したかったのですが)。
SELECT A from TABLE where isnumeric(A)=1
PATINDEXを使用する
DECLARE @input VARCHAR(10)='102030.40'
SELECT PATINDEX('%[^0-9]%',RTRIM(LTRIM(@input))) AS IsNumber
参照 http://www.intellectsql.com/post-how-to-check-if-the-input-is-numeric/