Самый быстрый способ проверить, является ли символ цифрой? - PullRequest
2 голосов
/ 22 сентября 2011

У меня проблемы с функцией ISNUMERIC в sqlserver, когда она возвращает true для ','

Я анализирую почтовый код и пытаюсь определить, является ли второй символ (предположительно цифрой) 0или нет и делать что-то свое в каждом случае.Проблема в том, что я не могу просто разыграть char, сначала проверив isNumeric.Вот код моей скалярной функции, которая возвращает цифру во втором расположении символа, и -1, если это не цифра.

@declare firstDigit int

IF ISNUMERIC(SUBSTRING(@postal,2,1) AS int) = 1
   set @firstDigit = CAST(SUBSTRING(@postal,2,1) AS int)
ELSE
   set @firstDigit = -1       

RETURN @firstdigit

Так как это происходит, когда почтовый индекс не совсем корректен.Я просто пытаюсь выяснить, как проверить, является ли второй символ nvarchar @postal цифрой от 0 до 9.Я видел различные типы решений, такие как LIKE [0-9] или PATINDEX и т. Д.

Есть ли лучший / более простой способ сделать это, и если нет, какой метод будет самым быстрым?

РЕДАКТИРОВАТЬ: Код добавлен в соответствии с предложением Аарона Бертран

ON z.postal = 
   CASE
      WHEN CONVERT(INT, CASE WHEN SUBSTRING(v.patientPostal,2,1) LIKE '[0-9]' 
          THEN SUBSTRING(v.patientPostal, 2,1) END) = 0 then v.patientPostal
      WHEN CONVERT(INT, CASE WHEN SUBSTRING(v.patientPostal,2,1) LIKE '[0-9]' 
          THEN SUBSTRING(v.patientPostal, 2,1) END) > 0 then LEFT(v.patientPostal,3)

Ответы [ 3 ]

7 голосов
/ 22 сентября 2011

Я был бы очень удивлен, если бы вы когда-нибудь смогли обнаружить разницу между WHERE col LIKE '[0-9]' и любыми другими методами, которые вы придумали.Но я согласен с Денисом: поместите это в функцию, чтобы вы последовательно использовали одну и ту же проверку во всем коде (или, по крайней мере, если вы избегаете UDF из-за больших сканирований и т. Д., Поместите в код маркер, который будетупростить изменение в широких масштабах позже).

Тем не менее, вы наверняка увидите большее снижение производительности, просто используя скалярную UDF, чем какой метод вы используете для анализа внутри функции.Вы действительно должны сравнить производительность UDF с выполнением этого в строке, используя CASE.например,

SELECT Postal = CONVERT(INT, CASE WHEN SUBSTRING(postal,2,1) LIKE '[0-9]' 
       THEN SUBSTRING(postal, 2,1) END)
FROM ...

Это даст NULL, если символ не является числовым.

Если вы имеете дело только с проверкой локальных переменных, на самом деле не имеет значения, какой метод разбора вы используетеиспользуйте, и вам лучше сосредоточить свои усилия по оптимизации в другом месте.

РЕДАКТИРОВАТЬ , добавив предложение к продемонстрированному предложению JOIN.Это может привести к менее постоянному сканированию, но намного более читабельно (гораздо меньше вызовов подстрок и т. Д.):

;WITH v AS 
(
    SELECT /* other columns, */ patientPostal, 
      ss = SUBSTRING(v.patientPostal,2,1),
      FROM [whatever table is aliased v in current query]
)
SELECT /* column list */
FROM [whatever table is aliased z in current query]
INNER JOIN v ON z.postal = CONVERT(INT, CASE 
    WHEN v.ss = '0' THEN ss
    WHEN v.ss LIKE '[1-9]' THEN LEFT(v.patientPostal, 3)
END);
3 голосов
/ 22 сентября 2011

Лучший способ сделать это это:

IF SUBSTRING(@postal,2,1) LIKE [0-9]
CAST(SUBSTRING(@postal,2,1) AS int)
1 голос
/ 22 сентября 2011

Взгляните на IsNumeric, IsInt, IsNumber есть проверки для этих 3 типов

...