このISNUMERIC
関数には予期しない動作があります。MSDNドキュメントには次のように書かれています。
ISNUMERIC
入力式が有効な数値データ型に評価されると1を返します。有効な数値データ型には、int、bigint、smallint、tinyint、decimal、numeric、money、smallmoney、float、realが含まれます。
また、脚注もあります。
ISNUMERIC
プラス(+)、マイナス(-)などの数字ではない一部の文字、およびドル記号($)などの有効な通貨記号に対して1を返します。通貨記号の完全なリストについては、「money and smallmoney(Transact-SQL)」を参照してください。
わかりましたので+
、-
、と記載されている通貨記号は、数値と見なされることが期待されます。ここまでは順調ですね。
奇妙な部分です。まず、リンクされた記事の通貨記号の一部は数値ではありません。
- ユーロ通貨記号、16進数20A0:
₠
- ナイラサイン、ヘックス20A6:
₦
- リアルサイン、16進FDFC:
﷼
これは奇妙で、なぜなのかわかりませんか?このバージョンまたは環境に依存していますか?
しかし、物事は奇妙になります。私が説明できない他のいくつかはここにあります:
/
数値ではありませんが、\
です(ハァッ!!)REPLICATE(N'9', 308)
数値ですが、そうでREPLICATE(N'9', 309)
はありません
最初の最も基本的な質問は、上記のケースを説明するものは何ですか?さらに重要なことですが、背後ISNUMERIC
にあるロジックは何ですか?したがって、すべてのケースを自分で説明/予測できますか?
物を再現する良い方法は次のとおりです。
DECLARE @tbl TABLE(txt NVARCHAR(1000));
INSERT INTO @tbl (txt)
VALUES (N''), (N' '), (N'€'), (N'$'), (N'$$'),
(NCHAR(8356)), (NCHAR(8352)), (NCHAR(8358)), (NCHAR(65020)),
(N'+'), (N'-'), (N'/'), (N'\'), (N'_'), (N'e'), (N'1e'), (N'e1'), (N'1e1'),
(N'1'), (N'-1'), (N'+1'), (N'1+1'), (N'⒈'), (N'🄂'), (N'¹'), (N'①'), (N'½'),
(N'🎅'), (REPLICATE(N'9', 307)), (REPLICATE(N'9', 308)), (REPLICATE(N'9', 309)),
(REPLICATE(N'9', 310));
SELECT UNICODE(LEFT(txt, 1)) AS FirstCharAsInt,
LEN(txt) AS TxtLength,
txt AS Txt,
ISNUMERIC(txt) AS [ISNUMERIC]
FROM @tbl;
これをローカルのSql Server 2012ボックスで実行すると、次の結果が得られます。
FirstCharAsInt TxtLength Txt ISNUMERIC
--------------- ---------- --------- ----------
NULL 0 0
32 0 0
8364 1 € 1
36 1 $ 1
36 2 $$ 0
8356 1 ₤ 1
8352 1 ₠ 0 --??
8358 1 ₦ 0 --??
65020 1 ﷼ 0 --??
43 1 + 1
45 1 - 1
47 1 / 0
92 1 \ 1 --??
95 1 _ 0
101 1 e 0
49 2 1e 0
101 2 e1 0
49 3 1e1 1
49 1 1 1
45 2 -1 1
43 2 +1 1
49 3 1+1 0
9352 1 ⒈ 0
55356 2 🄂 0
185 1 ¹ 0
9312 1 ① 0
189 1 ½ 0
55356 2 🎅 0
57 307 /*...*/ 1
57 308 /*...*/ 1 --??
57 309 /*...*/ 0 --??
57 310 /*...*/ 0
0
は、実際にうまくキャストされた5つの値を誤って報告することmoney
です。その他は正確に見えます。SQL FIDDLE