字符串表达式要计算为数字

时间:2012-03-24 10:16:47

标签: sql-server tsql evaluate

我需要编写一个TSQL用户定义函数,它将接受一个字符串并返回一个数字。

我会调用像dbo.EvaluateExpression('10*4.5*0.5')这样的函数应该返回数字22.5

任何人都可以帮我写这个函数EvaluateExpression

目前我正在使用我需要避免的CLR功能。

EDIT1

我知道这可以使用存储过程完成,但我想在ex select 10* dbo.EvaluateExpression('10*4.5*0.5')

的某些语句中调用此函数

此外,我还有大约400,000个这样的公式需要评估。

EDIT2

我知道我们可以在函数内部使用osql.exe来解决here。但由于权限设置,我也不能使用它。

5 个答案:

答案 0 :(得分:6)

我认为在用户定义的函数中不可能。

您可以在存储过程中执行此操作,例如:

declare @calc varchar(max)
set @calc = '10*4.5*0.5'

declare @sql nvarchar(max)
declare @result float
set @sql = N'set @result = ' + @calc
exec sp_executesql @sql, N'@result float output', @result out
select @result

但是在用户定义的函数中不允许使用动态SQL,如execsp_executesql

答案 1 :(得分:3)

免责声明:我是该项目的所有者Eval SQL.NET

对于SQL 2012+,您可以使用可以使用SAFE权限运行的Eval SQL.NET。

性能很好(优于UDF)并且尊重运算符优先级和括号。事实上,几乎所有的C#语言都受到支持。

您还可以为公式指定参数。

-- SELECT 225.00
SELECT 10 * CAST(SQLNET::New('10*4.5*0.5').Eval() AS DECIMAL(18, 2))

-- SELECT 70
DECLARE @formula VARCHAR(50) = 'a+b*c'
SELECT  10 * SQLNET::New(@formula)
                    .Val('a', 1)
                    .Val('b', 2)
                    .Val('c', 3)
                    .EvalInt()

答案 2 :(得分:0)

使用此功能,绝对有效。

CREATE FUNCTION dbo.EvaluateExpression(@list nvarchar(MAX))

RETURNS Decimal(10,2)
AS

BEGIN
Declare @Result Decimal(10,2)
set @Result=1
 DECLARE @pos        int,
       @nextpos    int,
       @valuelen   int

SELECT @pos = 0, @nextpos = 1


WHILE @nextpos > 0
  BEGIN
     SELECT @nextpos = charindex('*', @list, @pos + 1)
     SELECT @valuelen = CASE WHEN @nextpos > 0
                             THEN @nextpos
                             ELSE len(@list) + 1
                        END - @pos - 1

                        Set @Result=@Result*convert(decimal(10,2),substring(@list, @pos + 1, @valuelen))


     SELECT @pos = @nextpos
  END

RETURN @Result
END

您可以使用此

Select 10* dbo.EvaluateExpression('10*4.5*0.5')

答案 3 :(得分:0)

我认为你应该使用递归来编写自己的func。也许使用反向波兰表示法

是有用的

答案 4 :(得分:0)

You can use the SQL Stored procedure below to calculate the result of any formula with any number of variables:

I wrote in 2012 a solution which can evaluate any type of Mathematical formula using SQL SERVER. The solution can handle any formula with N variables :

I was asked to find a way to evaluate the value given by a Formula which is filled by the user. The Formula contains mathematical operations (addition, multiplication, division and subtractions) The parameters used to calculate the formula are stored in the SQL server DATA BASE.

The solution I found by myself was as follows:

Suppose I have n parameters used to calculate the formula, each of these parameters is stored in one row in one data table.

  • The data table containing the n rows to use in the formula is called tab_value

  • I have to store the n values found in n rows (in tab_values) in one single row in one new Table, using SQL cursor,

  • for that I create a new table called tab_formula

  • In the cursor, I will add a new column for each value, the column name will be Id1,Id2,Id3 etc.

  • Then I construct a SQL script containing the formula to evaluate the formula

Here after the complete script, I hope you find it useful, you are welcome to ask me about it.

The procedure uses as input:

-The formula

-A table containing the values used to calculate the formula

if exists(select 1 from sysobjects where name='usp_evaluate_formula' and xtype='p') drop proc usp_evaluate_formula go

create type type_tab as table(id int identity(1,1),val decimal(10,2)) go create proc usp_evaluate_formula(@formula as nvarchar(100),@values as type_tab readonly) as begin --KAMEL GAZZAH --kamelgazzah@gmail.com --05/09/2016

declare @tab_values table (id int, val decimal(10,2))

delete from @tab_values insert into @tab_values(id,val) select * from @values

declare @id as int declare @val as decimal(10,2)

if not exists(select 1 from sysobjects where name ='tab_formula') create table tab_formula(id int identity(1,1), formula nvarchar(1000)) if not exists(select 1 from tab_formula where formula=@formula) insert into tab_formula(formula) values(@formula)

declare c cursor for select id,val from @tab_values declare @script as nvarchar(4000) open c fetch c into @id,@val while @@fetch_status=0 begin set @script = 'if not exists(select 1 from syscolumns c inner join sysobjects o on c.id=o.id where o.name=''tab_formula'' and c.name=''id'+convert(nvarchar(3),@id)+ ''') alter table tab_formula add id'+convert(nvarchar(3),@id)+ ' decimal(10,2)' print @script exec(@script) set @script='update tab_formula set id'+convert(nvarchar(3),@id)+'='+convert(nvarchar(10),@val)+' where formula='''+@formula+'''' print @script exec(@script) fetch c into @id,@val end close c deallocate c

set @script='select *,convert(decimal(10,2),'+@formula+') "Result" from tab_formula where formula='''+@formula+'''' print @script exec(@script)

end

go

declare @mytab as type_tab insert into @mytab(val) values(1.56) insert into @mytab(val) values(15) insert into @mytab(val) values(25) insert into @mytab(val) values(32) insert into @mytab(val) values(17) insert into @mytab(val) values(33) insert into @mytab(val) values(37.9)

exec usp_evaluate_formula'cos(id1)+cos(id2)+cos(id3)+cos(id4)+cos(id5)+cos(id6)+cos(id7)/cos(Id6)',@mytab

go drop proc usp_evaluate_formula drop type type_tab drop table tab_formula