patternsqlModerate
What is the logic behind ISNUMERIC for certain special characters?
Viewed 0 times
theisnumericwhatlogicspecialforbehindcharacterscertain
Problem
The
And it also has a footnote:
Okay, so
Now for the odd part. First up, some of the currency symbols from linked article are not numeric, including:
This is weird, and I can't seem to find out why? Is this version or environment dependent?
However, things get weirder. Here are a few others I can't explain:
The first and most basic question is: what explains the above cases? More importantly though: what is the logic behind
Here's a good way to reproduce things:
```
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 [ISNU
ISNUMERIC function has some unexpected behavior. The MSDN documentation says:ISNUMERIC returns 1 when the input expression evaluates to a valid numeric data type; otherwise it returns 0. Valid numeric data types include the following: int, bigint, smallint, tinyint, decimal, numeric, money, smallmoney, float, real.And it also has a footnote:
ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($). For a complete list of currency symbols, see money and smallmoney (Transact-SQL).Okay, so
+, -, and listed currency symbols are expected to be considered numeric. So far so good.Now for the odd part. First up, some of the currency symbols from linked article are not numeric, including:
- Euro-Currency sign, hex 20A0:
₠
- Naira sign, hex 20A6:
₦
- Rial sign, hex FDFC:
﷼
This is weird, and I can't seem to find out why? Is this version or environment dependent?
However, things get weirder. Here are a few others I can't explain:
/is not numeric, but\is (Huh?!)
REPLICATE(N'9', 308)is numeric, butREPLICATE(N'9', 309)is not
The first and most basic question is: what explains the above cases? More importantly though: what is the logic behind
ISNUMERIC, so I could explain / predict all cases myself?Here's a good way to reproduce things:
```
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 [ISNU
Solution
The detailed behaviours of
As you are using SQL Server 2012, there is no need to use
ISNUMERIC are not documented, and probably not fully known to anyone without source code access. That said, it may be that interpretation depends on the Unicode categorization (numeric or not). Equally, the weird cases you mention may be bugs that are preserved for backwards compatibility. Yes I know that sounds crazy, but it does happen.As you are using SQL Server 2012, there is no need to use
ISNUMERIC. Use TRY_CONVERT or the synonymous TRY_CAST instead to check if a string is convertible to a given type. Where they provide adequate functionality, these are preferable to TRY_PARSE, because the latter involves more expensive processing via CLR integration.Context
StackExchange Database Administrators Q#76834, answer score: 13
Revisions (0)
No revisions yet.