2012-03-24 60 views
6

我需要编写一个TSQL用户定义的函数,它将接受一个字符串并返回一个数字。字符串表达式将被评估为数字

我会打电话像dbo.EvaluateExpression('10*4.5*0.5')函数应该返回人数22.5

任何一个可以帮我写这个功能EvaluateExpression

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

EDIT1

我知道这可以使用存储过程来完成,但我想调用这个函数在一些语句例如:select 10* dbo.EvaluateExpression('10*4.5*0.5')

我也有大约40万的公式是这样进行评估。

EDIT2

我知道我们可以使用OSQL.EXE内部功能做得一样解释here。但由于权限设置,我也不能使用这个。

+0

的可能重复的[存储在数据库式(方程式)将在后面进行评估(SQL Server 2005中)](http://stackoverflow.com/questions/9722782/storing-formula-方程式在数据库中要评估后来sql-server-2005) – Pondlife 2012-03-26 11:25:51

+0

你说你有一个工作的CLR功能,但“需要避免”它。如果你能解释原因,这将有所帮助; TSQL不是一个很好的语言,你可能会遇到更多的问题,而不仅仅是使用CLR。 – Pondlife 2012-03-26 11:26:57

+0

我试图避免CLR获得性能和安全原因 – PraveenVenu 2012-03-27 04:26:55

回答

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,在用户定义的函数是不允许的。

+0

Yah。我已经尝试过了,但是我想在一些语句中调用这个函数,例如:select * 10 * dbo.EvaluateExpression('10 * 4.5 * 0.5')' – PraveenVenu 2012-03-24 10:24:12

+1

AFAIK,这是无法在没有CLR支持的情况下完成的,函数的限制是[相当广泛](http://msdn.microsoft.com/en-us/library/ms191320.aspx) – Andomar 2012-03-24 10:34:20

+0

@PraVn:你可能想详细说明你想做什么,特别是在这些表达式来自。也许你可以将表达式和一些键一起存储到临时表中,让存储过程评估表达式,然后在查询/查询中使用临时表(使用上述键加入),读取/使用结果。 – 2012-03-24 21:57:33

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 @[email protected]*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') 
+0

它将适用于给定示例。但它不会评估所有表达式。对于例如:'10 +20'将失败 – PraveenVenu 2012-03-24 14:31:18

+1

以这种方式来确认运算符优先级或括号很难,f.e. '10 + 20 *(5 + 1)' – Andomar 2012-03-24 22:21:11

+0

Andomar,你的代码对此是正确的。谢谢 – 2012-07-13 09:12:53

0

我想你应该写自己的FUNC使用递归。也许这将是有益使用逆波兰式

3

免责声明:我的项目Eval SQL.NET

对于SQL 2012+,你可以使用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() 
0

可以使用SQL存储过程以下任意数量的变量计算任何公式的结果:

我在2012年写的,可以评估任何类型的使用SQL Server数学公式的解决方案。该解决方案可以处理任何具有N个变量的公式:

我被要求找到一种方法来评估由用户填充的公式给出的值。 公式包含数学运算(加法,乘法,除法和减法) 用于计算公式的参数存储在SQL服务器DATA BASE中。

我发现我自己的解决方案是如下:

假设我有n个用于计算式的参数,这些参数的每被存储在一个行中的一个数据表。 - 包含要在公式中使用的n行的数据表称为tab_value - 我必须在一个新表中使用SQL游标 - 将n行(在tab_values中)中找到的n个值存储在一行中我创建一个名为tab_formula的新表格 - 在游标中,我将为每个值添加一个新列,列名称将为Id1,Id2,Id3等。 - 然后我构造一个SQL脚本,其中包含公式以评估公式

这里完整的脚本后,我希望你觉得它有用,欢迎你问我。

该过程使用作为输入:含有用于计算公式

如果存在的值 -The式 -A表(从系统对象选择1其中name = 'usp_evaluate_formula' 和的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 开始 --KAMEL GAZZAH [email protected] --05/09/2016

声明@tab_values表(ID INT,VAL十进制(10,2))

从@tab_values删除插入@tab_values(ID,VAL) SELECT * FROM @values

声明@id为INT声明@val为十进制(10,2)

如果不存在(选择1从系统对象,其中name =” tab_formula') create table tab_formula(id int identity(1,1),式为nvarchar(1000)) 如果不存在(来自tab_formula选择1其中式= @式)插入到 tab_formula(式)的值(@formula)

c声明光标选择ID,从VAL声明@tab_values @脚本为 nvarchar(4000)打开c将文件提取到@id,@val而@@ fetch_status = 0 开始设置@script ='如果不存在(从syscolumns中选择1内部 在c.id = o上加入sysobjects o .id其中o.name =''tab_formula''和 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)+'其中 公式='''+ @ formula +''''print @script exec(@script)将c取回为 @ id,@ val end close c deallocate c

set @ script ='select *,convert(decimal(10 ,2), '+ @式+') “结果” 从tab_formula其中式= '' '+ @式+' ''”打印@Script EXEC(@Script)

声明@mytab作为type_tab插入@mytab(VAL)的值(1.56)插入到 @mytab(VAL)的值(15)插入到@mytab(VAL)的值(25)插入到 @mytab(VAL)的值(32)插入到@mytab(VAL)的值(17)插入到 @mytab(VAL)的值(33)插入到@mytab(VAL)的值(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降型type_tab降表 tab_formula

相关问题