no recursion (L to R no precedence either) - needs a tally table - uses the split like logic:
-- select dbo.fnSimpleMath( '3.5 * 2.2' ) , dbo.fnSimpleMath( '3 + 8' ) , dbo.fnSimpleMath( '5' ), dbo.fnSimpleMath( '3 / 4 + 3.2 ' ) , dbo.fnSimpleMath( '1/0' )
alter function dbo.fnSimpleMath(@string varchar(max))
returns numeric(18,6)
as begin
declare @math as table ( [sign] varchar(1), [orderby] int, addby numeric(18,6), subby numeric(18,6), multby numeric(18,6), divby numeric(18,6))
insert into @math values
('+',2,1.0,0,0,0)
,('-',2,0,1.0,0,0)
,('*',1,0,0,1.0,0)
,('/',1,0,0,0,1.0)
declare @StringSep varchar(max) = replace(replace(replace(replace(@String, '+','|'), '-','|'), '/','|'), '*','|')+ '|'
declare @result numeric(18,6) = 0
select
@result = ((@result + data )* isnull(math.addby,1.0) )
+ ((@result - data )* isnull(math.subby,0) )
+ (@result * data * isnull(math.multby ,0) )
+ isnull((@result / nullif(data,0) * isnull(math.divby ,0) ),0)
from
(select
convert(numeric(18,6), SUBSTRING(@String, Numbers.N+1 ,CHARINDEX('|', @StringSep , Numbers.N+1) - Numbers.N-1)) as data
,SUBSTRING(@String, Numbers.N, 1) as symbol
FROM dbo.Tally Numbers WITH (NOLOCK)
WHERE Numbers.N <= LEN(@String)
AND SUBSTRING('|'+@StringSep, Numbers.N+1, 1)='|'
) T
left outer join @math math
on math.sign = symbol
return @result
end
I really like the xml method stated above but am unable to get it to work dynamically without an error like The argument 1 of the XML data type method "query" must be a string literal.
declare @string varchar(max) = '3.5 * 2.2'
select convert(numeric(18,6),CONVERT(varchar(max), CONVERT(xml,'').query(@string)))