Я думаю, что это соответствует вашей спецификации. Это является довольно громоздким, но, надеюсь, это разрушает условия достаточно, что это явно делать правильные вещи, или, если это не так, что это достаточно легко изменить:
declare @t table (data varchar(30))
insert into @t(data) values
('1234'),
('1.23'),
('abc'),
('.abc'),
('+6000'),
('1.2.3')
select
CASE WHEN
Possible = 1 AND
(DecCheck = 0 OR
SingleDec = 1
) THEN
CONVERT(decimal(12,3),data)
END
from
@t t
cross apply
(select
--Only contains the correct characters
CASE WHEN not t.data like '%[^0-9.]%' THEN 1 ELSE 0 END as Possible,
--Contains a decimal point? (Needs more checks)
CASE WHEN CHARINDEX('.',t.data) > 0 THEN 1 ELSE 0 END as DecCheck,
CHARINDEX('.',t.data) as FirstDec --Where the first decimal point is
) p
cross apply
(select
CASE WHEN DecCheck = 1 THEN
--Only contains one decimal point
CASE WHEN LEN(data) = FirstDec + CHARINDEX('.',REVERSE(data)) - 1
THEN 1
ELSE 0 END
ELSE 0 END as SingleDec
) d
Результаты:
data
------------------------------ ---------------------------------------
1234 1234.000
1.23 1.230
abc NULL
.abc NULL
+6000 NULL
1.2.3 NULL
Т.е. одна дополнительная проверка, которую вы можете использовать, заключается в том, что десятичная строка не может быть первым или последним символом в строке. Это достаточно легко сделать, добавив эти дополнительные проверки в первый CASE
для столбца SingleDec
.
HI! попробуйте это, выберите * из вашей таблицы WHERE ISNUMERIC (yourfield) = 1 –
'ISNUMERIC' - это функция, которую никто никогда не просил и (довольно хорошо) никто не нуждается. Например. '1d1' и' £ 'считаются числами этой функцией, но ни одна из них не может быть преобразована в' int' или 'decimal()'. Они являются числовыми, потому что они могут быть преобразованы в * любые * числовых типов данных. Никто никогда не хочет раскрывать этот конкретный факт. –